[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RETURN-FROM inside a FINALLY
Date: Fri, 15 Sep 89 20:56 EDT
From: Barry Margolin <barmar@Think.COM>
Date: Fri, 15 Sep 89 10:21 PDT
From: Siskind.pa@xerox.com
This is a CommonLisp question not necessarily a
Symbolics question.
I have code which looks something like:
(loop named outer
collect (foo) into x
finally (loop for y in x
when (bar y)
do (return-from outer x))
(return nil))
The idea is that the outer loop does some work and builds a
list. When it is finished, the second loop in the finally
clause munges over that result. If a certain criteria is met
for any of the elements of the list, then the whole list is
returned by the return-from. Otherwise the, outer loop returns
nil. This works fine on both the L/G-machine and Ivory. When
I compile this in Lucid I get an error telling me that
there is no block named NIL when compiling (return-from outer x).
I can get arround this by doing:
(block outer
(loop collect (foo) into x
finally (loop for y in x
when (bar y)
do (return-from outer x))
(return nil)))
which works fine but I don't know whether the first example is
incorrect CommonLisp code or whether it is a problem with Lucid.
Jeff
-------
First of all, Common Lisp (as defined by CLtL) doesn't include the fancy
LOOP syntax; ANSI Common Lisp is expected to, though.
What appears to be happening is that the NAMED clause is specifying the
name for the BLOCK that LOOP creates, and this is overriding the default
name of NIL; when leaving a named loop, you must use (RETURN-FROM <name>
<val>). Genera, however, creates a block named NIL *and* a block with
the specified name, so that either (RETURN <val>) or (RETURN-FROM <name>
<val>) will work.
Your workaround seems OK. You could also change the second (RETURN NIL)
form to (RETURN-FROM OUTER NIL).
The draft ANSI LOOP spec isn't very clear about this. In several places
it says that a RETURN <val> clause is equivalent to DO (RETURN <val>),
which implies that there should always be a block named NIL. Lucid is
pretty tricky about this -- if the loop is named, it translates a RETURN
clause into the appropriate RETURN-FROM form. I'm copying this response
to the X3J13 Iteration Subcommittee to alert them to this ambiguity in
the draft.
barmar
This is a documentation error in the draft. However, it is clear that
the "intent" of Genera loop and the intent of the "other" derivations
diverged sometime way in the past.
Even back in 1983, the "update" to LOOP documentation I was maintaining
back at MIT contained an explicit example about this sort of case,
stating that (as Barry says above) one needs to use RETURN-FROM instead
of RETURN to return from a named loop. (This did make it into print as
part of the NIL Reference Manual.) This same documentation contains the
erroneous equivalence of "RETURN <form>" with "DO (RETURN <form>)".
I have since (back in 1986 or thereabouts) converted that LOOP to
Common-Lisp and distributed it, with just these semantics (one block
name).
The Genera model of LOOP naming and returns is really the Zetalisp model
of PROG naming and returns of several years ago. Under this model, and
ignoring "transparent" PROGs, RETURN always from the innermost PROG,
irrespective of its name. As Genera has developed, these semantics have
been carefully preserved in loop.
I am of the opinion that LOOP, with a single NAMED clause, should
establish a single block with that name, and not establish a block named
NIL. I do not believe this to be a correction or even clarification of
any kind; documentation of the NAMED clause is quite explicit. However,
X3J13/89-004 p. 2-36 says the clause "RETURN <value>" is equivalent to
"DO (RETURN <value>)", and this should be corrected to something like
"DO (RETURN-FROM <loop-name> <value>)" with reference to the NAMED
clause.
It has also been suggested that the NAMED clause should be modified so
that multiple NAMED clauses are permitted. With no NAMED clause the
LOOP establishes one block named NIL; with one or more NAMED clause, the
LOOP establishes that many blocks, one with each name. This is
something that has cropped up as a possible extension in the past. In
the case of this incompatibility, would aid in mechanical conversion of
Genera-style loop to ANSI-style with minimal textual change. Anyone
else have any feelings about this?