Subject: Re: design and lisp
From: rpw3@rpw3.org (Rob Warnock)
Date: Mon, 02 Aug 2004 19:38:12 -0500
Newsgroups: comp.lang.lisp
Message-ID: <Qr6dncSoZ7PpQ5PcRVn-gw@speakeasy.net>
Kenny Tilton  <ktilton@nyc.rr.com> wrote:
+---------------
| Paolo Amoroso wrote:
| > What's wrong, i.e. un-Lispy, with long LET binding lists?
| 
| If a binding is used in only one place, it creates needless noise and 
| makes code harder to read. Long binding lists generally also mean that a 
| function can usefully be broken up into smaller functions. Sometimes a 
| long binding list has bindings used only in one branch of the following 
| logic. That's a waste and also noise. etc etc etc
+---------------

On the other hand, breaking a long LET* into a bunch of smaller functions
can *also* create needless noise, when the LET* actually makes things
clearer by documenting a complex calculation by using single-assignment
variables to name intermediate results (subexpressions).

I find myself using this most in functions which return a newly-allocated
object of some type, particularly when there are minor decisions and
cross-checks to be made. You end up with a template of the form:

    (defun make-checked-FOO (args...)
      (let* ((field1 (or (some-computation-on-args...)
			 (alternate-computation...)
			 default))
             (field2 ...)
             (field3 ...)
	     (cse1 (intermediate-result-of args... field[123]...))
	     (field4 (some-computation args... cse1))
	     (field5 (other-computation args... cse1)))
	(make-FOO :field1 field1
	          :field2 field2
	          :field3 field3
	          :field4 field4
	          :field5 field5)))

And even when helper functions *are* needed, often a local FLET or
LABELS is the way to go. By keeping all of the tricky logic in one
place, clarity can be improved.

Or not. Obviously, if the individual computations start getting *very*
complex, they should be moved out to separate functions. I certainly
admit I have been guilty of writing monstrous LET*'s and later seeing
that they really needed refactoring to call external functions. It
all comes down to doing whichever minimizes complexity and maximizes
long-term maintainability [which includes readability]...


-Rob

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