Joost Kremers <joostkremers@...> writes:
> so is this a bug in CLisp's DOLIST, or is there something else going
> on?
This sounds like it's related to the discussion in this thread¹ from a
couple of years ago entitled "Midfunction Recursion." I asked several
questions in that thread, and rereading it now I can say my grasp of
it has only marginally improved. One of Tim Bradshaw's replies² best
matches and enhances my current understanding, while several other
replies seem to assert the inverse explanation. Perhaps I had lost
track of what we were arguing about.
In any case, I'll try to address your example. With CLISP, dolist
establishes one binding for key and assigns it on each iteration.
(let ((r))
(dolist (key '(1 2 3 4 5) r)
(push #'(lambda ()
(format t "~A" key))
r)))
(LET ((R))
(BLOCK NIL
(LET* ((#:G23090 '(1 2 3 4 5)) (KEY NIL)) (DECLARE (LIST #:G23090))
(TAGBODY #:G23091 (IF (ENDP #:G23090) (GO #:G23092))
(SETQ KEY (CAR #:G23090))
(SETQ R
(CONS
#'(LAMBDA NIL (DECLARE (SYSTEM::SOURCE (NIL (FORMAT T "~A" KEY))))
(FORMAT T "~A" KEY))
R))
(SETQ #:G23090 (CDR #:G23090)) (GO #:G23091) #:G23092
(RETURN-FROM NIL (LET ((KEY NIL)) (DECLARE (IGNORABLE KEY))
R))))))
You can see this more easily in the macroexpansion for a similar DO
form (Erik Naggum's example):
(do ((i 1 (1+ i))
(foo () (cons (lambda () i) foo)))
((= i 5) foo))
(BLOCK NIL
(LET ((I 1) (FOO NIL))
(TAGBODY #:G23080 (IF (= I 5) (GO #:G23081))
(PSETQ I (1+ I) FOO
(CONS #'(LAMBDA NIL (DECLARE (SYSTEM::SOURCE (NIL I))) I) FOO))
(GO #:G23080) #:G23081 (RETURN-FROM NIL FOO))))
It looks like CLISP implements DOLIST in terms of DO and, according to
the Hyperspec, DO is guaranteed to use assignment to a single binding:
At the beginning of each iteration other than the first, vars are
updated as follows. All the step-forms, if supplied, are evaluated,
from left to right, and the resulting values are assigned to the
respective vars.
Note that on DOLIST the HyperSpec says³:
It is implementation-dependent whether dolist establishes a new
binding of var on each iteration or whether it establishes a binding
for var once at the beginning and then assigns it on any subsequent
iterations.
That lets both CLISP and SBCL off the hook.
Footnotes:
¹ http://groups.google.com/groups?threadm=3244459363713506%40naggum.no
² http://groups.google.com/groups?threadm=ey3adl3btrn.fsf%40cley.com
³ http://www.lispworks.com/reference/HyperSpec/Body/m_dolist.htm
--
Steven E. Harris

hi list,
while writing a small program that uses ltk to create a simple GUI, i ran into
the following code that works on SBCL but doesn't on CLisp:
(dolist (key '(1 2 3 4 5 6 7 8 9 0))
(bind *tk* (format nil "~A" key) (lambda (e) (declare (ignore e))
(key-press key))))
i'm simply trying to avoid writing this 10 times:
(bind *tk* "1" (lambda (e) (declare (ignore e)) (key-press 1)))
with the 1's appropriately replaced by 2, 3, etc., of course.
like i said, the code works as i expect it would on SBCL, i.e., it creates a
binding for the key "1" to (key-press 1), for "2" to (key-press 2), etc. but it
doesn't on CLisp. i did some experimenting:
(dolist (key '(1 2 3 4 5 6 7 8 9 0))
(bind *tk* (format nil "~A" key) (lambda (e) (declare (ignore e))
(princ key))))
replacing the call to KEY-PRESS to PRINC, so that i can see what is actually
happening. now, every time i press any of the number keys, a zero is printed on
stdout. if i change the list to e.g. '(0 1 2 3 4 5 6 7 8 9), pressing any
number key results in a 9 to be printed to stdout. IOW the code creates a
binding for each of the number keys to (key-press 0), or (key-press 9),
depending on whatever the last element of the list is.
BTW, doing the same with mapcar works ok:
(mapcar #'(lambda (key)
(bind *tk* (format nil "~A" key) (lambda (e) (declare (ignore e))
(key-press key))))
'(0 1 2 3 4 5 6 7 8 9))
so is this a bug in CLisp's DOLIST, or is there something else going on?
TIA
joost
FYI:
joost@...:~/programs/nos-tt $ clisp --version
GNU CLISP 2.33.2 (2004-06-02) (built 3301301325) (memory 3301301683)
joost@...:~ $ uname -rsmo
Linux 2.4.22-ben2 ppc GNU/Linux
__________________________________
Do you Yahoo!?
Check out the new Yahoo! Front Page.
http://www.yahoo.com