Loop for and behaviour
From: Antonio Menezes Leitao (Antonio.Leitao_at_evaluator.pt)
Date: 05/24/04
- Previous message: Ng Pheng Siong: "Re: Is Lisp more than another language?"
- Next in thread: David Steuber: "Re: Loop for and behaviour"
- Reply: David Steuber: "Re: Loop for and behaviour"
- Reply: Antonio Menezes Leitao: "Re: Loop for and behaviour"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Mon, 24 May 2004 01:09:28 +0100
Hi,
After seeing so many complains regarding one of my challenges for
translation from Common Lisp to Java I decided to investigate it. I
must warn that I'm not a loop expert and all my loops were (and are)
quite simple so I might be wrong about all this. I hope someone can
clarify the issue for me. The challenge in question is the following:
(defun test5 ()
(let ((x 10))
(loop for x from 1 to 9
and y = x then x
sum (+ x y))))
I was under the impression that the 'and' loop keyword would cause x and y
to be bound in parallel. In fact, the Hyperspec says:
6.1.1.5.1 Summary of Variable Initialization and Stepping Clauses
The for and as constructs provide iteration control clauses that
establish a variable to be initialized. for and as clauses can be
combined with the loop keyword and to get parallel initialization and
stepping[1]. Otherwise, the initialization and stepping[1] are sequential.
"Parallel initialization and stepping" sounded just like the difference
between 'do' and 'do*'. And I confirmed this idea when I read:
6.1.2.1 Iteration Control
If multiple iteration clauses are used to control iteration, variable
initialization and stepping[1] occur sequentially by default. The and
construct can be used to connect two or more iteration clauses when
sequential binding and stepping[1] are not necessary. The iteration
behavior of clauses joined by and is analogous to the behavior of the
macro do with respect to do*.
Not being a loop expert, this made me think that the above loop should
have been identical to the following:
(defun test5 ()
(let ((x 10))
(let ((sum 0))
(do ((x 1 (1+ x))
(y x x))
((> x 9) sum)
(incf sum (+ x y))))))
However, everybody was complaining that the outer 'x' was an unused
variable. I tried my example in a lot of Common Lisps and, in fact, they
all agreed with everybody's opinion (except mine). Where was my error?
After further reading the Hyperspec, I found the following possible
explanation:
6.1.1.4 Expanding Loop Forms
Implementations can interleave the setting of initial values with the
bindings. However, the assignment of the initial values is always
calculated in the order specified by the user. A variable is thus
sometimes bound to a meaningless value of the correct type, and then
later in the prologue it is set to the true initial value by using setq.
One implication of this interleaving is that it is
implementation-dependent whether the lexical environment in which the
initial value forms (variously called the form1, form2, form3, step-fun,
vector, hash-table, and package) in any for-as-subclause, except
for-as-equals-then, are evaluated includes only the loop variables
preceding that form or includes more or all of the loop variables; the
form1 and form2 in a for-as-equals-then form includes the lexical
environment of all the loop variables.
Note the exception made of the for-as-equals-then. It looks like the
outer 'x' is, after all, unused, because the 'y' is within the scope
of the inner 'x'. That's odd. I couldn't understand the rational for
that behaviour so I digged a little further and I found the long
discussion of the Issue
LOOP-INITFORM-ENVIRONMENT:PARTIAL-INTERLEAVING-VAGUE but after reading it
I became even more confused because it seems that it agrees with me. They
even include the following example as a test case:
(let ((list '(1 2 3)))
(loop for list = list then (cdr list)
until (null list)
collect (car list)))
=> (1 2 3)
If you try this, I bet your Common Lisp implementation will warn that the
outer 'list' is unused and then the result is NIL and not (1 2 3).
I noted that the Issue status is 'For X3J13 consideration' but I couldn't
see if it was accepted or rejected. I presume it was rejected.
So, I remain puzzled. Is there a rational for the 6.1.1.4 Expanding Loop
Forms paragraph that I presented above?
Thanks in advance,
Antonio Leitao.
- Previous message: Ng Pheng Siong: "Re: Is Lisp more than another language?"
- Next in thread: David Steuber: "Re: Loop for and behaviour"
- Reply: David Steuber: "Re: Loop for and behaviour"
- Reply: Antonio Menezes Leitao: "Re: Loop for and behaviour"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|