[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
EVAL
Date: Wed, 26 Nov 86 00:24:12 EST
From: Alan Bawden <ALAN@AI.AI.MIT.EDU>
Subject: EVAL
To: mike%acorn@LIVE-OAK.LCS.MIT.EDU
cc: common-lisp@SU-AI.ARPA, Fahlman@C.CS.CMU.EDU,
Sean.Engelson@CAD.CS.CMU.EDU
In-reply-to: Msg of Tue 25 Nov 86 02:36 est from mike%acorn at mit-live-oak.arpa
Message-ID: <123570.861126.ALAN@AI.AI.MIT.EDU>
Date: Tue, 25 Nov 86 02:36 est
From: mike%acorn at mit-live-oak.arpa
Date: Sat, 22 Nov 86 17:32 EST
From: Alan Bawden <Alan@AI.AI.MIT.EDU>
... This demonstrates that LEXICAL-EVAL would have to be a new
special form, rather than simply a function.
This same issue seems to come up over and over. Will someone tell
me what is wrong with the following argument:
I see no reason for "lexical-eval" or any eval with an environment arg.
The following is a trivial source-to-source you can use to get the
effect of a lexical eval:
Suppose you wanted
(defun foo (s-exp)
(let ((x 5))
(flet ((bar (y) (+ x y)))
(block here
(tagbody :there
(lexical-eval s-exp))))))
this is exactly equivalent to:
(defun foo (s-exp)
(eval
`(let ((x 5))
(flet ((bar (y) (+ x y)))
(block here
(tagbody :there
,s-exp))))))
which does not use any "lexical-eval". Since the primary
effect of the compiler is to eliminate lexical environments, any
lexical "stuff" surrounding a call to "lexical-eval" can't really
be compiled (not much anyway) since it all might be referred to
by the s-expression being evaled. This being the case, the
second form here, which just eval's the entire lexical scope,
is roughly as efficient.
No, it's -roughly- equivalent to:
(defun foo (s-exp)
(eval `(let ((s-exp ',s-exp))
(let ((x 5))
(flet ((bar (y) (+ x y)))
(block here
(tagbody :there ,s-exp)))))))
and even then it doesn't address the issue of what happens if S-EXP
contains code that destructively modifies the list structure in the
object held by S-EXP. My rewrite, which at least appropriately binds
the variable S-EXP, makes that be well-behaved, which is not a
semantics-preserving transformation.
I'm not quite sure what your proposed source transformation was supposed to
demonstrate. How do you compile
(defun bind-x-then-call-f (x f)
(funcall f `(cons x x)))
given that anyone can do
(bind-x-then-call-f 'foo #'lexical-eval)?
Right. Your remark about how this could be done as a special form
thwarts the ability to do this (since you can't do #'<special-form>)
and hides the potential problem in a fortuitous way. The real issue,
of course, is that this is the power people -want-. They want things
like EVAL-IN-CLOSURE, which are the problemsome cases, because the
introduction of such into the language ties the hands of the compiler
and doesn't allow any optimization.
I think Mike's intent is correct, though, in that the situations where
you might want LEXICAL-EVAL in cases that are constrained adequately so
as not to break the language are handled adequately by his suggested
rewrite using EVAL. The cases that are not handled by that rewrite --
and not at all by coincidence -- are the cases which strike fear in the
hearts of compiler maintainers everywhere.
Moreover, using LEXICAL-EVAL invites many of the name collision problems
that the move to lexical scoping did away with.
(DEFUN F (X Y) (+ X (EVAL Y)))
used to be a problem in dynamic lisps because the local X and Y would
interfere with the EVAL (at least in the interpreter and also in some
compilers). In a lexical Lisp, such as CL, the name collision problem
doesn't happen. Allowing people to do LEXICAL-EVAL there is just asking
for the same unwanted name collisions that we were trying to get away
with in CL.
I concur with those who have said we should explicitly document the
rationale for the absence of this primitive in the next CL language spec.
- References:
- EVAL
- From: Alan Bawden <ALAN@AI.AI.MIT.EDU>