[cl-faq] faq answer: Why are there both LET and LET*?
Larry Clapp
larry at theclapp.org
Wed Jun 21 08:23:14 CDT 2006
*** Why are there both LET and LET*?
LET and LET* both calculate values and establish bindings. They
differ in when they do it. LET calculates all values, and then
establishes new bindings all at once, in parallel. LET* binds each
variable to a new value one at a time, serially.
This Lisp
(let (a b c) ; ignore this for now
(setq a 1)
(setq b 2)
(setq c 3)
(let ((a 10)
(b (1+ a))
(c (1+ b)))
(format t "~D ~D ~D~%" a b c)))
prints=> 10 2 3
is similar to this C
int a, b, c;
a = 1;
b = 2;
c = 3;
int tmp_a = 10;
int tmp_b = a + 1;
int tmp_c = b + 1;
a = tmp_a;
b = tmp_b;
c = tmp_c;
printf( "%d %d %d\n", a, b, c );
In the LET, the calculation of B cannot be affected by the new value
of A, because that new value has not been established yet. Similarly
for C not being affected by the new value of B. So we say that LET
binds variables "in parallel".
LET* doesn't work in parallel, but serially, one at a time.
(let (a b c) ; ignore this for now
(setq a 1)
(setq b 2)
(setq c 3)
(let* ((a 10)
(b (1+ a))
(c (1+ b)))
(format t "~D ~D ~D~%" a b c)))
prints=> 10 11 12
is equivalent to
(let (a b c) ; ignore this for now
(setq a 1)
(setq b 2)
(setq c 3)
(let ((a 10))
(let ((b (1+ a)))
(let ((c (1+ b)))
(format t "~D ~D ~D~%" a b c)))))
prints=> 10 11 12
is similar, but not equivalent, to
int a, b, c;
a = 1;
b = 2;
c = 3;
a = 10;
b = a + 1;
c = b + 1;
printf( "%d %d %d\n", a, b, c );
In fact, the * in LET* is sort of like the * in regular expressions:
LET* means "multiple LETs". See
http://en.wikipedia.org/wiki/Regular_expression and
http://en.wikipedia.org/wiki/Kleene_star.
Note on "similar but not equivalent": the difference arises because
after the LET/LET*, all the variables they bind are restored to their
former values, which the above C code doesn't do. It could, of course
-- C has block-sloped variables, too -- but I've omitted that for
clarity.
-- Larry
More information about the cl-faq
mailing list