[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: EVAL-WHEN (really symbol-function)
I think it is time we back off for a second from what is in the book, and
just think about what makes sense for Common LISP. I would advocate
making the restriction I have suggested explicit: "It is an error to
setf the symbol-function to an object not of type FUNCTION." Also, the
implementation should be at liberty to store the functional interpretation
of a lambda or symbol if that is what setf is given. Note that this
doesn't restrict the implementation from setting it in the case of a macro
or special form. My real concern is that no gain is made by making
the function cell completely general, and there are some losses (consistency
with (setf (macro-function...)) and performance). It seems every time
we get into a discussion about an ambiguity, we always make a change that
tends to make the language more complicated. Why can't we try for simplicity
this time (I really don't see that we are losing anything)?
All this hidden hash concept does for you is give the user one function cell
and the implementation an other one. What good is the user function cell if
the system isn't even using it?
If anybody has a reason why the restriction I mention above interferes with
execution of correct code, please say so (don't tell me about doing an
EQL test before and after a (setf (symbol-function...)) because that is what
we are disputing. I mean when would someone legitimately write a piece of
Common LISP with non-function items in the function cell (unless they
were simply using it as a value cell)? Until someone can generate such an
example, I see no reason why some people are so tenaciously insisting that
anything can be stored in the funtion cell.
Consider what happens if you allow arbitrary objects in the function cell
as in the following example:
(setf x '(lambda () "Hi"))
(setf (symbol-function 'y) x)
(setf (third x) "Bye")
What is this supposed to return? In an implementation which guarantees that
the value stored really is EQL to the one given, it seems reasonable that
"Bye" would be returned. But in order to make that work, the implementation
couldn't use the hidden hash method because it wouldn't reflect the change.
It would still have to interpret each time! You can always say that it doesn't
have to reflect the list surgery, but then what's the point of requiring that
the result be EQL?
Date: Wed, 9 Apr 86 21:08:05 GMT
From: Jeff Dalton <email@example.com>
Subject: Re: EVAL-WHEN (really symbol-function)
Date: 8 Apr 1986 17:34-EST
3. Under interp 1. consider the following:
(defun foo () (print "hello"))
(setf (symbol-function 'bar) 'foo)
Which of the following are legal?:
(funcall 'bar) ; A
(funcall #'bar) ; B
(funcall (symbol-function 'bar)) ; C
Case C is the only one I am sure is legal. The other two depend on
the ambiguous description of function calling (pg. 58) and APPLY (pg.
Case C should be legal because it should be the same as (funcall 'foo).
Case B should also be legal because #'bar == (function bar) should be
equivalent to (symbol-function 'bar) in a context where bar refers to a
global function (i.e., when there's no lexically enclosing flet or
labels that binds bar), as it does in this case.
One of (:->) the definitions of FUNCTION on pg. 87 states that "FN is
interpreted as if it had appeared in the functional position of a
function invocation". As most of us would agree (but CLtL does not
pin down), the function call (bar) is erroneous (again, CLtL does not
define what should happen when the function definition is illegal or
even unbound). By this definition of FUNCTION then, (function bar) is
erroneous. Up until now, I think most people thought that (bar) and
(funcall (function bar)) were semantically equivalent (i.e., both are
illegal). By your definition of FUNCTION (as being eqiv. to
SYMBOL-FUNCTION in the case of a global function name), the former is
still illegal but the latter is perfectly legal. Yecch! I'll stick
with my reading of FUNCTION.
The definition of FUNCTION (on page 87) also says:
"If fn is a symbol, the functional definition associated with that symbol is
returned; see symbol-function." Yecch is right, but that's what it says!
I guess my point is that I think most implementors followed
interpretation 2 which prevents the kind of confusion where C is legal
but B is not; so we should clarify CLtL in that direction rather than
towards interp 1.
I don't think there is a case where C should be legal and B not.
As I showed above, I think there is.
Thank you for pointing out pg 32. It states that "The result of
evaluating a FUNCTION special form will always be a function." If we
accept this statement. Then under interp. 2:
(setf (symbol-function 'zap) 1.0)
What does this return?:
(function zap) =>
A) 1.0 ; According to your definition of FUNCTION.
B) <<a function that when called will barf>>.
C) Undefined by CL (implementations are encouraged to signal an error).
I hope that I have made my point that interp. 2 is unintuitive (since
most implementations didn't do it that way) and leads to confusion.
Well, based on the statement I quoted above from FUNCTION, it must be A, but
based on the statement you quoted from page 32, that is impossible. Again,
I can only conclude that only objects of type FUNCTION should be allowed
in the function cell! I still believe that the only way the statements
about FUNCTION (page 32 and 87) can be interpreted consistently is if
function cells are only allowed to contain objects which are FUNCTIONP.
Equally important is the point which Nick makes, namely that it is much
more intuitive (and consistent with (setf (macro-function...)) (which states
that "the value installed must be a function ...") Indeed, SYMBOL-FUNCTION
says much the same thing: "the definition may be a function or an object
representing a special form or macro [ underlining added by me]"