Subject: Re: `let*' and functional design
From: rpw3@rpw3.org (Rob Warnock)
Date: Mon, 11 Jul 2005 00:06:33 -0500
Newsgroups: comp.lang.lisp
Message-ID: <jvOdnUMvIYzEY0zfRVn-tQ@speakeasy.net>
jayessay  <nospam@foo.com> wrote:
+---------------
| "Kaz Kylheku" <kkylheku@gmail.com> writes:
| > I don't see how you can lump LET* in the same category as RPLACA.
| > That's just weird.
| 
| I absolutely agree.  It's hard to imagine PG's motivation for doing
| so; I mean he can't possibly be that clueless.
| 
| Frankly, I think the problem with LET* is the *.  It would have been
| better if LET* had been LET and LET had been LET*, but whatever.
+---------------

Or maybe LET & PLET, by analogy to SETQ & PSETQ or SETF & PSETF.

By the way, LET* can encourage a sort of SSA ["Static Single Assignment",
see <http://en.wikipedia.org/wiki/Static_single_assignment_form>] style
of programming that gets rid of a bunch of unnecessary mutations (SETFs)
by giving each new result either a new name or a new scope for the old
name. So if you're doing some kind of "step by step" algorithm, at least
you can use rebinding/renaming instead of mutation [which has potential
performance advantages for generational collectiors, by the way]. Though
as others have noted it can also create readability issues due to the
renaming. That is, when used badly you end up with this:

    (let* ((tmp (create-first-value))
	   (tmp (some-function tmp))
	   (tmp (some-other-function tmp))
	   (tmp (some-last-function tmp)))
      ...use TMP ...)

or worse, some mix of temp names, with the data flow all mixed up:

    (let* ((tmp0 (create-first-value))
	   (tmp1 (another-first-value))
	   (tmp0 (some-function tmp0))
	   (tmp0 (some-other-function tmp0))
	   (tmp0 (some-function tmp0 tmp1))
	   (tmp1 (some-third-function tmp0))
	   (tmp (some-last-function tmp0 tmp1)))
      ...use TMP ...)

On the other hand, deep-but-readable LET* style is quite commonly
seen in XLIB-based windowing code:

   (let* ((display (server-display server))
	  (screen (server-screen server))
	  (fg-color (server-black server))
	  (bg-color (server-white server))
	  (font (open-font display font))
	  (text-height (+ (max-char-ascent font) (max-char-descent font)))
	  (text-width (text-width font "Thu Jan  1 00:00:00 1970"))
	  (height (* 2 (+ text-height text-margin)))
	  (width (+ text-width (* 2 text-margin)))
	  (window (create-window :parent (screen-root screen)
				 :x x :y y :width width :height height
				 :background bg-color))
	  (gc (create-gcontext :drawable window
			       :background bg-color
			       :foreground fg-color
			       :font font)))
     (set-wm-properties window :name title
			       :icon-name "simple clock"
			       :user-specified-position-p t)
     (map-window window)
     (make-clock :display display :screen screen
                 :window window :gc gc
                 :x x :y y :height height :width width
                 :title title :font font
                 :bg-color bg-color :fg-color fg-color
                 :text-x text-margin
                 :text-y (+ (max-char-ascent font) text-margin)))


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607