[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Clarification of closures and GO
- To: jonl at PARC-MAXC
- Subject: Clarification of closures and GO
- From: Guy.Steele at CMU-10A
- Date: Sat, 04 Sep 1982 03:39:00 -0000
- Cc: common-lisp at SU-AI, moon@scrc-tenex at MIT-MC, hedrick at rutgers
1) Glaaag, did the CL meeting *really* ditch the notion of being able
to include special variables into closures? I thought it merely decided
to extend the LispM syntax to include all lexically appearing variables
by default (sort of what NIL was proposing to do) which would mean
current LispM closures would be a subset of the future closures.
First of all, as has already been pointed out on the mailing list,
the word "closure" has been used to mean different things. Here I will
always speak explicitly of "closures over lexical variables" and
"closures over special variables".
The CL meeting did *not* vote to get rid of either kind of closure.
It was to have been an item on the agenda at Hedrick's request, and I
apologize greatly for having overlooked it. Subsequent to the meeting
the notion of eliminating closures over special variables has been
discussed on the net. As nearly as I can tell, so far there is some
sympathy for eliminating them, and no ardent voices for retaining them.
However, a formal poll has not been conducted.
The current state of Common LISP with respect to closures is as follows:
bound variables that are not special are lexical (not local--if a compiler
can suitably determine that a lexical variable is not referred to from within
a nested lambda-expression, then it is welcome to treat it as local; this
static analysis can be performed at compile time). Therefore the FUNCTION
construct containing a lambda-expression may need to construct a closure
over lexical variables. Again, in the interpreter it is probably simplest
to close over all lexical variables, but compiled code can close over
only those variables that are needed (possibly none).
There is a separate construct, called CLOSURE, that constructs closures
over special variables. It takes any function and an explicit list of
names of special variables, and constructs a closure over precisely those
special variables and no others. It does not close over any lexical
variables whatsoever. If you write
(DECLARE (SPECIAL B))
(LET ((A 0) (B 1))
(CLOSURE #'(LAMBDA (X Y) (+ A B X Y)) '(B)))
then the result of the CLOSURE operation indeed closes over both
A (a lexical variable) and B (a special variable), but for completely
independent reasons. The use of FUNCTION implied by #' caused A to
be closed over before the CLOSURE operation ever executed.
2) I can't believe we agreed to support full funarging. That's incredible!
Only the spaghetti stack does this "right", for the pseudo-mathematical
concept you mention, and CL is nowhere near spaghetti yet. The
alternative is to ditch Lisp semantics and go for Scheme, and I hope
there hasn't been any consensus on that!!!
Well, full lexical scoping as well as dynamic scoping has been agreed to;
along with CLOSURE, that's a full as I've ever seen any funarging get.
Even without CLOSURE, one still has closures over lexical variables,
which I suppose is what some people mean by "full funarging". It is
debatable whether spaghetti stacks "do it right" (I would refer you
to my 1977 paper "Macaroni is Better than Sphagetti", except
that I don't believbe that Macaroni *is* better; nevertheless that
paper contains a critique of spaghetti stacks that may be relevant).
Even if they do "do it right", it is debatable whether that is the only
I'm sure that Common LISP hasn't gone for SCHEME, and I suspect the T folks
at Yale would back me up there. While Common LISP, as currently defined,
supports lexical scoping, it also supports dynamic scoping in pretty
much the traditional style, and furthermore differs from SCHEME in having
separate value and function cells.
3) Yea, my myopic misreading of Hedrick caused me to say issue #68 (and
#62) when I meant #8. But again, the consensus was to allow any local
GO (local includes all the cases in issue #8 except from within funargs);
Non-local GO's, such as could be the case from within funargs, were
certainly argued against, so I'd hardly say there was consensus on this
point; wouldn't such non-local GO's ultimately imply spaghetti also?
The consensus of the recent meeting was that PROG tags, to which GO's
refer, would have lexical scope and *dynamic extent*. The effect of that
last phrase is to make them behave like a CATCH followed by a local GO.
That is, once you have exited a PROG by whatever means, its tags are
no longer valid and you may not GO to them.