LET versus LET* in Common Lisp

LET itself is not a real primitive in a Functional Programming Language, since it can replaced with LAMBDA. Like this:

(let ((a1 b1) (a2 b2) ... (an bn))
  (some-code a1 a2 ... an))

is similar to

((lambda (a1 a2 ... an)
   (some-code a1 a2 ... an))
 b1 b2 ... bn)

But

(let* ((a1 b1) (a2 b2) ... (an bn))
  (some-code a1 a2 ... an))

is similar to

((lambda (a1)
    ((lambda (a2)
       ...
       ((lambda (an)
          (some-code a1 a2 ... an))
        bn))
      b2))
   b1)

You can imagine which is the simpler thing. LET and not LET*.

LET makes code understanding easier. One sees a bunch of bindings and one can read each binding individually without the need to understand the top-down/left-right flow of ‘effects’ (rebindings). Using LET* signals to the programmer (the one that reads code) that the bindings are not independent, but there is some kind of top-down flow – which complicates things.

Common Lisp has the rule that the values for the bindings in LET are computed left to right. Just how the values for a function call are evaluated – left to right. So, LET is the conceptually simpler statement and it should be used by default.

Types in LOOP? Are used quite often. There are some primitive forms of type declaration that are easy to remember. Example:

(LOOP FOR i FIXNUM BELOW (TRUNCATE n 2) do (something i))

Above declares the variable i to be a fixnum.

Richard P. Gabriel published his book on Lisp benchmarks in 1985 and at that time these benchmarks were also used with non-CL Lisps. Common Lisp itself was brand new in 1985 – the CLtL1 book which described the language had just been published in 1984. No wonder the implementations were not very optimized at that time. The optimizations implemented were basically the same (or less) that the implementations before had (like MacLisp).

But for LET vs. LET* the main difference is that code using LET is easier to understand for humans, since the binding clauses are independent of each other – especially since it is bad style to take advantage of the left to right evaluation (not setting variables as a side effect).

Leave a Comment