Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

FUNCALL question

136 views
Skip to first unread message

Bruce Krulwich

unread,
Jan 28, 1990, 6:47:11 PM1/28/90
to
Why is FUNCALL a function in CL? It seems to me that it should be as
efficient to do a FUNCALL (say, to a lexically bound variable) as a
standard function call. However, if FUNCALL is a function it will
require twice the overhead because two function calls are being done (one
to FUNCALL and one to the function being called).

Rough experiments in Lucid CL (on a SPARCstation) indicate that there is
indeed twice the procedure-call overhead in calling a closure stored in a
lexically bound variable as in calling a global function (stored in a
symbol's function slot).

I use the example of a lexically bound variable because it is a case
where there is _more_ information available at compile-time about the
location of the function to be called as in the case of a global
function.

I suppose I have two questions:

(1) Why isn't this something that implementations optimize?
(2) Why does the CL standard have FUNCALL as a function?

My guess is that the answer to (1) is "because the CL spec says it's a
function" and that the answer to (2) is "because no implementation
handles it differently."

(As a side issue, this seems to be yet another example of the emphasis of
different programming methodologies in CL and Scheme, and their effect on
both the syntactic clumsiness and code efficiency in the two languages.)

I'm interested in knowing any actual reasons for FUNCALL to strictly be a
function, or for implementations not to optimize it heavily to be no less
efficient than a standard function call.


Bruce Krulwich
krul...@ils.nwu.edu


Sandra J Loosemore

unread,
Jan 28, 1990, 7:54:37 PM1/28/90
to
In article <32...@accuvax.nwu.edu> krul...@ils.nwu.edu (Bruce Krulwich) writes:
>Rough experiments in Lucid CL (on a SPARCstation) indicate that there is
>indeed twice the procedure-call overhead in calling a closure stored in a
>lexically bound variable as in calling a global function (stored in a
>symbol's function slot).

Careful -- you're comparing apples and oranges here.

In many Lisp implementations, there is more overhead involved in
calling a closure than in calling a function that is not closed,
independently of whether the function is stored as a local variable or
as a global function. This overhead typically involves doing
something like an extra set of register save/loads on entry and return,
and an extra jump.

> (1) Why isn't this something that implementations optimize?

Many implementations do optimize FUNCALL heavily. It is theoretically
possible to compile FUNCALL to be just as efficient as an ordinary
call to a named global function, provided that the object being called
is known to be a true function at compile-time (and not a symbol, for
example). In the absence of declarations, though, you have to go
through a runtime call to do the appropriate type-checking and
coercion on the function argument, which will slow things down. This
is usually not necessary on a call to a named global function -- it is
common to do the checking and coercion in advance to insure that the
object stored in the SYMBOL-FUNCTION "cell" of a symbol is always a
true function.

> (2) Why does the CL standard have FUNCALL as a function?

Without FUNCALL or APPLY, every function would have to be named and you
would have to know the name of every function your program calls in
advance. It would be impossible to pass a function as an argument to
the SORT function, for example. Even C and FORTRAN have similar
syntactic constructs.

FUNCALL is nicer than APPLY because it can be better optimized by the
compiler (no need to cons up an argument list). And it's a function
(as opposed to a special form) because it has functional semantics --
it does not have funny syntax and all of its arguments are always
evaluated in left-to-right order.

-Sandra Loosemore (san...@cs.utah.edu)

g...@paradigm.com

unread,
Jan 29, 1990, 2:11:35 PM1/29/90
to
There used to be a saying, FUNCALL CONSIDERED HARMFULL..

In article <1990Jan28.1...@hellgate.utah.edu>, sandra%defun.u...@cs.utah.edu (Sandra J Loosemore) writes:
> In article <32...@accuvax.nwu.edu> krul...@ils.nwu.edu (Bruce Krulwich) writes:
>>Rough experiments in Lucid CL (on a SPARCstation) indicate that there is
>>indeed twice the procedure-call overhead in calling a closure stored in a
>>lexically bound variable as in calling a global function (stored in a
>>symbol's function slot).
>

> Many implementations do optimize FUNCALL heavily. It is theoretically
> possible to compile FUNCALL to be just as efficient as an ordinary

> call to a named global function ...

Enough theory, here are some fun-facts-to-know and tell.

(1) In the MIT CADR or LMI LAMBDA lispmachine (FUNCALL F X) and (F X) compiled
into *exactly* the same machine instructions.
(2) The case (FUNCALL F X) where F was a local variable was very slightly,
but measurably FASTER than the case of (F X) where F was a "global"
(3) Symbolics and then later Texas Instruments improved on the instruction
set such that (FUNCALL F X) and (F X) were indeed different, resulting
in some extra overhead for the FUNCALL case, although it is very
difficult to measure the difference.
(4) On a VAX it is quite easy to implement lexical closures in such a way
(inline-code trampolines) such that the two cases produce the same
instructions.
(5) On some RISC architectures, e.g. SPARC from SUN, there is different
code produce for {This is C code now, not lisp:} (*F)(X); vs. F(X);
and in-fact a little subroutine called POINTERCALL is called
in the (*F)(X); case.


-GJC

(Also known as the John Silber of Lisp Implementors?)

John Gateley

unread,
Jan 29, 1990, 4:17:48 PM1/29/90
to
In article <32...@accuvax.nwu.edu> krul...@ils.nwu.edu (Bruce Krulwich) writes:
>I use the example of a lexically bound variable because it is a case
>where there is _more_ information available at compile-time about the
>location of the function to be called as in the case of a global
>function.

This is confusing the issue somewhat: if you have a lexical variable bound
to a function you know lots about, you should be using LABELS instead
of let/let*. Then you don't need funcall. If you aren't binding it to
a lambda, then chances are you don't know that much about the function
anyways.

John
gat...@m2.csc.ti.com

lawrence.g.mayka

unread,
Jan 30, 1990, 9:44:01 AM1/30/90
to
In article <3...@forsight.Jpl.Nasa.Gov> g...@robotics.Jpl.Nasa.Gov (Erann Gat) writes:
>necessary buy you a great deal of efficiency, whereas in Common LISP,
>the semantics buy you a great deal of confusion. It is not necessary to have
>multiple bindings to have a robust, efficient LISP. In Scheme, to cite but
>one example, symbols have only one binding, and funcall is thereby dispensed
>with, along with a few other hacks which CL had to introduce to deal
>with the mess that multiple bindings produces.

This issue is discussed - rather evenhandedly, I think - in
Gabriel and Pitman's article, "Endpaper: Technical Issues of
Separation in Function Cells and Value Cells," in the June 1988
(Vol. 1, No. 1) issue of "Lisp and Symbolic Computation."


Lawrence G. Mayka
AT&T Bell Laboratories
l...@ihlpf.att.com

Standard disclaimer.

Erann Gat

unread,
Jan 29, 1990, 5:33:35 PM1/29/90
to
In article <1990Jan28.1...@hellgate.utah.edu>, sandra%defun.u...@cs.utah.edu (Sandra J Loosemore) writes:
> Without FUNCALL or APPLY, every function would have to be named and you
> would have to know the name of every function your program calls in
> advance. It would be impossible to pass a function as an argument to
> the SORT function, for example. Even C and FORTRAN have similar
> syntactic constructs.

The first two statements are wrong, and the third is misleading at best.

I don't know (or care) about FORTRAN, but the C mechanism of
dereferencing a pointer to a function and calling the resulting function is
not the same as funcall. The difference lies in the underlying semantics
of the languages.

In C, all variable names refer to storage locations whose addresses are
determined at compile time. Thus, in C it is necessary to manually dereference
a pointer if you want the identity of a function call to be able to vary at
runtime (e.g. when calling a function passed as a parameter).

In LISP on the other hand, every variable (i.e. symbol) reference is automat-
ically (and transparently) dereferenced. However, in Common LISP, a symbol
can be dereferenced several different ways. A CL symbol has a value binding and
a function binding, and a few others as well. Usually, a function call to
a named function refers to the function binding of the symbol, but not
always. Notably, when you want to call a function which has been
passed as a parameter, you need to make a call to the symbol-value
of a symbol rather than the symbol-function. FUNCALL is used to make
a function call to a symbol's value binding.

The main difference (IMHO) is that in C, the semantics which make the syntax


necessary buy you a great deal of efficiency, whereas in Common LISP,
the semantics buy you a great deal of confusion. It is not necessary to have
multiple bindings to have a robust, efficient LISP. In Scheme, to cite but
one example, symbols have only one binding, and funcall is thereby dispensed
with, along with a few other hacks which CL had to introduce to deal
with the mess that multiple bindings produces.

Insert standard disclaimer here.

Sandra J Loosemore

unread,
Jan 30, 1990, 12:43:05 AM1/30/90
to
g...@robotics.Jpl.Nasa.Gov (Erann Gat) writes:
>Notably, when you want to call a function which has been
>passed as a parameter, you need to make a call to the symbol-value
>of a symbol rather than the symbol-function. FUNCALL is used to make
>a function call to a symbol's value binding.

This is totally incorrect. FUNCALL is used to call a functional *object*
and has nothing at all to do with how the value was obtained.
You don't "need" to make a call to symbol-value at all to use FUNCALL.
And although FUNCALL *can* be used to make a function call to a symbol's
value binding, it has many other uses as well.

Some examples may clarify. All of these end up causing exactly the same
function to be called.

This one does indeed go through the symbol-value of the symbol *function*,
which is declared to be a special variable:
(defvar *function* #'(lambda (x) (print x)))
(funcall *function* 3)

In this case, the #'lambda form returns a functional object directly:
(funcall #'(lambda (x) (print x)) 3)

Here I've stored it in a local variable. This does *not* go through the
the symbol-value cell of the symbol my-function because it is a lexical,
rather than special, binding. Typically, compilers will allocate storage
for this local variable in a register or on the stack, in exactly the
same way that C compilers allocate storage for local variables.
(let ((my-function #'(lambda (x) (print x))))
(funcall my-function 3))

Both of the following two are similar to the previous one, except they
create a functional binding of the symbol my-function instead of a variable
binding. I think many compilers probably generate exactly the same code
for all three of these.
(flet ((my-function (x) (print x)))
(funcall #'my-function 3))
(flet ((my-function (x) (print x)))
(my-function 3))

Here is one that is even more complicated. It calls another function
to compute the function to be applied.
(defun compute-a-function ()
#'(lambda (x) (print x)))
(funcall (compute-a-function) 3)

>In Scheme, to cite but
>one example, symbols have only one binding, and funcall is thereby dispensed
>with, along with a few other hacks which CL had to introduce to deal
>with the mess that multiple bindings produces.

Scheme has a FUNCALL operation with exactly the same *semantics* as
that in Common Lisp. It does, however, have different syntax, which
most people would probably agree is less complicated. In Common Lisp,
one would write

(funcall <expression-which-evaluates-to-a-function> . <arguments>)

while in Scheme one would write

(<expression-which-evaluates-to-a-function> . <arguments>)

-Sandra Loosemore (san...@cs.utah.edu)

Erann Gat

unread,
Jan 30, 1990, 1:33:19 PM1/30/90
to
In article <1990Jan29.2...@hellgate.utah.edu>, sandra%defun.utah.edu@cs.

utah.edu (Sandra J Loosemore) writes:
> g...@robotics.Jpl.Nasa.Gov (Erann Gat) writes:
> >Notably, when you want to call a function which has been
> >passed as a parameter, you need to make a call to the symbol-value
> >of a symbol rather than the symbol-function. FUNCALL is used to make
> >a function call to a symbol's value binding.
>
> This is totally incorrect. FUNCALL is used to call a functional *object*
> and has nothing at all to do with how the value was obtained.
> You don't "need" to make a call to symbol-value at all to use FUNCALL.
> And although FUNCALL *can* be used to make a function call to a symbol's
> value binding, it has many other uses as well.

I never meant to imply that funcall did not have other uses. My point was
that if you want to call a function stored in a symbol's symbol-value
(as it is when it is passed as a parameter) then you MUST use funcall
(or apply).

> >In Scheme, to cite but
> >one example, symbols have only one binding, and funcall is thereby dispensed
> >with, along with a few other hacks which CL had to introduce to deal
> >with the mess that multiple bindings produces.
>
> Scheme has a FUNCALL operation with exactly the same *semantics* as
> that in Common Lisp. It does, however, have different syntax, which
> most people would probably agree is less complicated.

Scheme has a FUNCALL only insofar as its semantics for calling functions
are the same as the semantics of funcall. Scheme does not have a
function which does what FUNCALL does. This may seem trivial, but my experience
has been that the existence of FUNCALL (and FUNCTION and FLET and #', etc.)
is the source of a great deal of confusion for beginning programmers,
a great deal of frustration for experienced ones, and a lot of wasted time
and effort implementing compilers which are more complicated than they
need to be. If anyone knows of a good reason to have an explicit FUNCALL
(which is to say, a good reason to distinguish between a symbol's function
binding and value binding) I wish they would point it out to me (preferably
via E-mail).

As long as I am picking on Common Lisp, let me air another of my pet peeves:
There seems to be no way to undo the global special declaration performed
by a DEFVAR. Once a symbol has been DEFVARed, there is no way to use that
symbol as a lexical variable ever again short of rebooting the environment.
You can really screw yourself over with a careless DEFVAR. This can be the
source of some EXTREMELY subtle and frustrating bugs.

-Erann Gat (g...@robotics.jpl.nasa.gov)

Barry Margolin

unread,
Jan 31, 1990, 12:39:35 AM1/31/90
to
In article <32...@accuvax.nwu.edu> krul...@ils.nwu.edu (Bruce Krulwich) writes:
>Why is FUNCALL a function in CL? It seems to me that it should be as
>efficient to do a FUNCALL (say, to a lexically bound variable) as a
>standard function call. However, if FUNCALL is a function it will
>require twice the overhead because two function calls are being done (one
>to FUNCALL and one to the function being called).

I think most production-quality Lisps open-code FUNCALL, so that you don't
double the procedure call overhead. FUNCALL is used all over the place in
the standard Lisp library (such as SORT, or any function that takes :TEST
or :KEY arguments), so it behooves the implementors to make FUNCALL fast.

I just looked at the compiled code for a FUNCALL on both a Sun-4 (running
Lucid 3.0.1) and a Symbolics 36xx (running Genera 7.2) and neither
generates a call to the FUNCALL function.

There is a little extra overhead in Lucid FUNCALL, because it must coerce
lambda expressions into function objects before calling them (this is
required by the CL spec).

>I use the example of a lexically bound variable because it is a case
>where there is _more_ information available at compile-time about the
>location of the function to be called as in the case of a global
>function.

What "more information"? In one case it's a stack frame offset, and in the
other case it's an offset from a pointer into the heap (the pointer to the
symbol). It's a common misconception that accessing global variable values
is slow in Lisp; people assume that it must go through the package hash
table, but that happens at READ or LOAD time, not at execution time.

> (2) Why does the CL standard have FUNCALL as a function?

Most likely because the Lisps from which CL is descended all had FUNCALL.

>(As a side issue, this seems to be yet another example of the emphasis of
>different programming methodologies in CL and Scheme, and their effect on
>both the syntactic clumsiness and code efficiency in the two languages.)

Whether FUNCALL is syntactically clumsy is a matter of opinion. However,
there is no reason for this syntactic issue to affect code efficiency. The
Scheme form (<form> . <args>) should compile into exactly the
same code as the CL form (funcall <form> . <args>).

>I'm interested in knowing any actual reasons for FUNCALL to strictly be a
>function, or for implementations not to optimize it heavily to be no less
>efficient than a standard function call.

There's no reason for implementations not to optimize it heavily. Don't
buy any that don't optimize, and you'll be doing your part to stamp them
out.
--
Barry Margolin, Thinking Machines Corp.

bar...@think.com
{uunet,harvard}!think!barmar

Andrew L. M. Shalit

unread,
Jan 31, 1990, 2:28:23 PM1/31/90
to
In article <16...@skye.ed.ac.uk> je...@aiai.ed.ac.uk (Jeff Dalton) writes:

However, nothing says an implementation can't provide some way to
turn off a SPECIAL proclamation (which is how DEFVAR makes the
variable special). There just isn't a standard way to do it.

Turning off a special proclamation would involve going through all the
compiled functions in the world which reference the variable, and
changing them to treat the variable as lexical. Some implementations
might be able to backpatch the functions, but others would probably
need to recompile them. Needless to say, this could be a *very*
expensive operation. (Don't forget to include the time needed
to walk all the functions in the world looking for the references.)

-andrew

Jeff Dalton

unread,
Jan 31, 1990, 11:13:52 AM1/31/90
to
>As long as I am picking on Common Lisp, let me air another of my pet peeves:
>There seems to be no way to undo the global special declaration performed
>by a DEFVAR. Once a symbol has been DEFVARed, there is no way to use that
>symbol as a lexical variable ever again short of rebooting the environment.
>You can really screw yourself over with a careless DEFVAR. This can be the
>source of some EXTREMELY subtle and frustrating bugs.

That's why it's a good idea to use the *<name>* convention. In that
case, the bugs occur only when you forget to do the DEFVAR., and they
aren't all that subtle.

However, nothing says an implementation can't provide some way to
turn off a SPECIAL proclamation (which is how DEFVAR makes the
variable special). There just isn't a standard way to do it.

This should probably be regarded as a programming environment issue.
Common Lisp addresses some programming environemnt issues (eg, TRACE)
and not others. This is one of the others.

One the other hand, while turning off a special proclamation would be
useful during debugging, it would not be a good idea for programs to
make use it so that, for example, on page one X is always special
and on page two it isn't.

-- Jeff

Jeff Dalton

unread,
Jan 31, 1990, 12:11:09 PM1/31/90
to
>In article <1990Jan29.2...@hellgate.utah.edu>, sandra%defun.utah.edu@cs.
>utah.edu (Sandra J Loosemore) writes:
>> Scheme has a FUNCALL operation with exactly the same *semantics* as
>> that in Common Lisp. It does, however, have different syntax, which
>> most people would probably agree is less complicated.

I'm not sure it's fair to say FUNCALL is just syntax, because FUNCALL
is not restricted to appearing as the car of a function call. FUNCALL
is a function, and Scheme does not have such a function. Since the
original quesiton was "why is FUNCALL a function?", this is a relevant,
although minor, point.

I think it's true that most people now prefer the Scheme approach; but
it depends, in part, on what sort of code is involved. When a lot of
FUNCALLs are needed, they can make code look cluttered and hard to
read. But when they're rare, they can act as a useful sign that
something unusual is happening.

>Scheme has a FUNCALL only insofar as its semantics for calling functions
>are the same as the semantics of funcall. Scheme does not have a
>function which does what FUNCALL does.

I agree (see above).

-- Jeff

Jeff Dalton

unread,
Jan 31, 1990, 1:14:48 PM1/31/90
to
In article <1990Jan29.2...@hellgate.utah.edu> sandra%defun.u...@cs.utah.edu (Sandra J Loosemore) writes:
>g...@robotics.Jpl.Nasa.Gov (Erann Gat) writes:
>>Notably, when you want to call a function which has been
>>passed as a parameter, you need to make a call to the symbol-value
>>of a symbol rather than the symbol-function. FUNCALL is used to make
>>a function call to a symbol's value binding.
>
>This is totally incorrect. FUNCALL is used to call a functional *object*
>and has nothing at all to do with how the value was obtained.
>You don't "need" to make a call to symbol-value at all to use FUNCALL.
>And although FUNCALL *can* be used to make a function call to a symbol's
>value binding, it has many other uses as well.

Well, it's not *totally* incorrect. Let me try to be clear. I pretty
much agree that everything Sandra Loosemore said is true, but I think
there is another way of looking at it that more or less agrees with
Erann Gat. Note too that, as I understand it, Erann is saying

if you want to call a function passed as a parameter, ... you need
to use FUNCALL

which, except for some possible confusion about symbol-value, is
true, and is not saying

if you use FUNCALL, you must be ...

which is what Sandra seems to be answering.

If we look at Common Lisp syntax, we find that identifiers can be
interpreted a function names or as variables. We also find that an
identifier is treated as a function when it appears as the first
element of a function call and as a variable when it appears as one of
the later elements. ["Form" is a Lisp term for "expression".]

<form> ::= <variable> | <function call> | <special form> | ...

<function call> ::= (<function> <form>*)

<special form> ::= ... | (FUNCTION <function>) | ...

<variable> ::= <identifier>

<function> ::= <identifier> | (LAMBDA <parameter list> <form>*)

Indeed, an identifier can be associated with two values at once,
one when it's interpreted as a function name, the other when it's
interpreted as a variable. Erann Gat made the mistake of calling
these two interpretations the symbol-function and symbol-value
when those terms are properly applied only to symbols (acting
as global variables and function names). Local variables and
function names don't have symbol-values or symbol-functions in
that sense. However, FUNCALL does have some connection with
the two-interpretation problem.

FUNCTION is used to get the functional interpretation of an identifier
or lambda-expression when it appears somewhere other than the first
element of a function call. That is, when the normal interpretation
of an identifier would be as a variable.

But suppose you have a variable whose value is a function and you want
to call that function. A syntactic solution, analogous to FUNCTION,
might be to have a notation like this:

((VARIABLE <variable>) <form>*)

That is, VARIABLE would let you get the variable interpretation when
the normal interpretation was as a function name, and the syntax of
<function> would be extended by:

<function> ::= ... | (VARIABLE <variable>)

However, Common Lisp chose a different solution, namely that of having
a function -- FUNCALL -- that calls functional objects. It lets you
write the variable in a place where it's interpretated as a variable,
making the VARIABLE notation unnecessary. That is, you write

(FUNCALL <variable> <form>*)

instead of the expression involving VARIABLE above. Of course, this
isn't the only use of FUNCALL.

Another solution to this problem would be to allow expressions (forms)
to appear as the first element of a function call. In Scheme, this
works in a straightforward way for variables, because there's only one
interpretation of identifiers. But in Lisp like Common Lisp, you'd
have to write something like

((IDENTITY <variable>) <form>*)

if you wanted the identifier to be interpreted as a variable.

On the whole, the FUNCALL solution seems a good one.

Jeff Dalton, JANET: J.Da...@uk.ac.ed
AI Applications Institute, ARPA: J.Dalton%uk.a...@nsfnet-relay.ac.uk
Edinburgh University. UUCP: ...!ukc!ed.ac.uk!J.Dalton

Erann Gat

unread,
Jan 31, 1990, 7:15:46 PM1/31/90
to
In article <16...@skye.ed.ac.uk>, je...@aiai.ed.ac.uk (Jeff Dalton) writes:
> Indeed, an identifier can be associated with two values at once,
> one when it's interpreted as a function name, the other when it's
> interpreted as a variable. Erann Gat made the mistake of calling
> these two interpretations the symbol-function and symbol-value
> when those terms are properly applied only to symbols (acting
> as global variables and function names). Local variables and
> function names don't have symbol-values or symbol-functions in
> that sense.

I want to thank Jeff Dalton for coming to my defense. However, the
above is totally incorrect (said with a smile). Temporary variables
do have value and function bindings. That is why there are LET and
FLET forms in CL. For example:

(flet ((x (x) (+ x x)))
(let ((x 1))
(x x)))

This horrible bit of code returns 2 (and is reason enough to abandon
multiple bindings, IMHO.)

> On the whole, the FUNCALL solution seems a good one.

Alas, this is probably true. My youthful idealism still clings to
the vain hope that we can escape the multiple-binding standard
somehow. (I am still eagerly awaiting the demise of FORTRAN as
well.)

-E.

Hunter Barr

unread,
Feb 1, 1990, 11:23:47 AM2/1/90
to

...

>Scheme has a FUNCALL only insofar as its semantics for calling functions
>are the same as the semantics of funcall. Scheme does not have a
>function which does what FUNCALL does. This may seem trivial, but my experience
>has been that the existence of FUNCALL (and FUNCTION and FLET and #', etc.)
>is the source of a great deal of confusion for beginning programmers,
>a great deal of frustration for experienced ones, and a lot of wasted time
>and effort implementing compilers which are more complicated than they
>need to be. If anyone knows of a good reason to have an explicit FUNCALL
>(which is to say, a good reason to distinguish between a symbol's function
>binding and value binding) I wish they would point it out to me (preferably
>via E-mail).
>
>As long as I am picking on Common Lisp, let me air another of my pet peeves:
>There seems to be no way to undo the global special declaration performed
>by a DEFVAR. Once a symbol has been DEFVARed, there is no way to use that
>symbol as a lexical variable ever again short of rebooting the environment.
>You can really screw yourself over with a careless DEFVAR. This can be the
>source of some EXTREMELY subtle and frustrating bugs.
>
>-Erann Gat (g...@robotics.jpl.nasa.gov)


The whole discussion of FUNCALL boils down to this: Erann doesn't like
Common Lisp overloading symbols by allowing separate value and
function cells. Erann deserves no criticism for that. I myself agree
that Scheme's scheme is much prettier in many ways. But in my actual
work I usually find it more convenient to overload symbols. (Keep in
mind that this says more about my personal style of programming and
thinking about problems than about anything else.) But some problems
*are* harder to untangle if you let your symbols get overloaded, while
other problems are harder if you are forced to spend time thinking up
different (but related) symbol-names for variables and associated
functions. Neither paradigm works best in all situations.

Now, about your pet peeve. DEFVAR is intended to be quite permanent,
and there should not be an approved way to undo it. If you need
something to be special, but you don't want to screw up your global
toplevel environment, don't do a DEFVAR. Instead, just declare it to
be special inside the toplevel function of your system. Give it the
customary stars to make it clear that you intend it to be special.
Try this:

<cl> (defun peeve-test ()
(let ((*peeve* 'pet))
(declare (special *peeve*))
(peeve-1)))
peeve-test
<cl> (defun peeve-1 ()
(describe '*peeve*))
peeve-1
<cl> (peeve-1)
*peeve* is a symbol
It is unbound
It is internal in the user package
<cl> (peeve-test)
*peeve* is a symbol
Its value is pet
It is internal in the user package
<cl> (peeve-1)
*peeve* is a symbol
It is unbound
It is internal in the user package
<cl>

See? Special variables with no mess left over. Even if you use
DEFVAR, if you follow the star-tradition you can avoid trouble by
never trying to use *<foo>* as a lexical variable. You wouldn't want
to (UN-DEFVAR *PRINT-BASE*) would you? Now that *would* cause some
problems.

Thanks for reading this far, everyone.
--
______
HUNTER

Richard Billington

unread,
Feb 1, 1990, 3:11:05 PM2/1/90
to
>In article <16...@skye.ed.ac.uk>, je...@aiai.ed.ac.uk (Jeff Dalton) writes:
>> Indeed, an identifier can be associated with two values at once,
>> one when it's interpreted as a function name, the other when it's
>> interpreted as a variable. Erann Gat made the mistake of calling
>> these two interpretations the symbol-function and symbol-value
>> when those terms are properly applied only to symbols (acting
>> as global variables and function names). Local variables and
>> function names don't have symbol-values or symbol-functions in
>> that sense.
>
>I want to thank Jeff Dalton for coming to my defense. However, the
>above is totally incorrect (said with a smile). Temporary variables
>do have value and function bindings. That is why there are LET and
>FLET forms in CL. For example:
>
>(flet ((x (x) (+ x x)))
> (let ((x 1))
> (x x)))
> ...

Hmmm, well there is certainly something more to what Jeff says than
your example allows. The point he makes is that temporary variables
are not equivalent to symbols, so his summary sentence is correct.
What he said does not preclude your example.

It is an important distinction to keep in mind. Forgetting that local
variables are not symbols, I wrote a stupid piece of cute code which
looked like the following:

(defun foo (x)
(flet ((hi () (print "hi there")) ;same for labels
(bye () (print "good-bye")))
(funcall x)))

and then got an error (that the function hi is undefined) when I
tried the following:

(foo 'hi)

Whereas the following works fine:

(defun hi () (print "hi there"))

(defun foo (x) (funcall x))

(foo 'hi) => "hi there"

This actually led me to some confusing results that only the rule
"local variables are not symbols" helped explain in anyway. Given
my first definition of foo, consider

(defun foo1 ()
(flet ((hi () (print "hi there")) ;same for labels
(bye () (print "good-bye")))
(funcall 'hi)))

(defun foo2 ()
(flet ((hi () (print "hi there")) ;same for labels
(bye () (print "good-bye")))
(funcall #'hi)))

foo2 works, foo1 doesn't. Now consider

(defun foo3 (x)
(let ((hi #'(lambda () (print "hi there")))
(bye #'(lambda () (print "hi there"))))
(funcall x)

This does work.

Having played around with this a bit, one thing is clear
to me local variables are not equivalent to symbols.

Jeff Dalton

unread,
Feb 1, 1990, 3:26:43 PM2/1/90
to
>In article <16...@skye.ed.ac.uk>, je...@aiai.ed.ac.uk (Jeff Dalton) writes:
>> Indeed, an identifier can be associated with two values at once,
>> one when it's interpreted as a function name, the other when it's
>> interpreted as a variable. Erann Gat made the mistake of calling
>> these two interpretations the symbol-function and symbol-value
>> when those terms are properly applied only to symbols (acting
>> as global variables and function names). Local variables and
>> function names don't have symbol-values or symbol-functions in
>> that sense.

>I want to thank Jeff Dalton for coming to my defense. However, the
>above is totally incorrect (said with a smile). Temporary variables
>do have value and function bindings. That is why there are LET and
>FLET forms in CL. For example:

No, you have it wrong -- this time. But it's because I failed to make
some things clear.

I tried to be careful to say "identifier" when I was talking about a
name in a program and "variable" and "function name" for the two
possible interpretations of identifiers (possible in the contexts we
were interested in, that is). In this terminology, a _variable_
doesn't have both a function and value binding, but a single name
might have both, in a sense, because it's being used as both a
variable and a function name.

We could shift terminology, however, and say that a variable can
have both a value and a function binding (as you say above). I
wasn't trying to disagree with you there.

However, once you say "symbol-value" and "symbol-function" people may
well assume you're talking about _symbols_ (the data objects) and the
associated values obtained by the Common Lisp functions SYMBOL-VALUE
and SYMBOL-FUNCTION. Indeed, I thought people were reading you that
way.

The problem with talking this way is that local variables might not
be associated with symbols at all -- after compilation, for example.
And, in any case, the functions SYMBOL-VALUE and SYMBOL-FUNCTION can't
look at local variables.

Anyway, that's the "sense" I had in mind when I wrote "local variables


and function names don't have symbol-values or symbol-functions in
that sense."

-- Jeff

Sandra J Loosemore

unread,
Feb 1, 1990, 11:26:52 PM2/1/90
to
>Nevertheless, I stand by the
>assertion that identifiers in Common Lisp, be they local or global,
>have two bindings, a value binding and a function binding,

Agreed, but they actually have more than two bindings. They can also
have type bindings, documentation-type bindings, declaration bindings,
and so on.

>and that
>this is the reason for the existence of an explicit FUNCALL function,
>that is, to enable one to call a function stored in an identifier's
>value slot.

No, the reason for the existence of the FUNCALL function is that in
Common Lisp syntax, the CAR of a list follows different evaluation
rules than subforms in the CDR. What FUNCALL buys you is the ability
to obtain the function to be called by evaluating something with the
CDR evaluation rules instead of the CAR evaluation rules. Although
it's hard to imagine why one would want to do such a thing, you could
certainly have a two-namespace Lisp that uses the same evaluation
rules in both CAR and CDR, and no explicit FUNCALL operation. You
would just have to use #'<function-name> as the CAR of every function
call form instead of just <function-name> so that you refer to the
functional binding of the name instead of its variable binding, as in

(#'list 'a 'b 'c)

One can also imagine a single-namespace Lisp that has different
evaluation rules for the CAR than the CDR, that would require an
explicit FUNCALL operator. The issues of syntax and namespaces are
actually orthogonal.

>I also reaffirm my position that multiple bindings cause a great deal of
>confusion!

I don't think anybody has been seriously taking issue with this. I'm
not too bothered by multiple namespaces in practice, but I agree that
a single namespace is less complicated.

-Sandra Loosemore (san...@cs.utah.edu)

Erann Gat

unread,
Feb 1, 1990, 8:04:13 PM2/1/90
to
In article <16...@skye.ed.ac.uk>, je...@aiai.ed.ac.uk (Jeff Dalton) writes:
> No, you have it wrong -- this time.

I stand corrected, and I apologize for my careless use of the terms
symbol-value and symbol-function. Nevertheless, I stand by the

assertion that identifiers in Common Lisp, be they local or global,

have two bindings, a value binding and a function binding, and that


this is the reason for the existence of an explicit FUNCALL function,
that is, to enable one to call a function stored in an identifier's
value slot.

I also reaffirm my position that multiple bindings cause a great deal of
confusion!

-Erann

Kellom{ki Pertti

unread,
Feb 2, 1990, 8:36:58 AM2/2/90
to
It seems to me that the whole mess with funcall is caused by
implementations that extend the Common Lisp as defined by CLtL. The
confusion stems from the semantics of funcall. CLtL states that

"(funcall fn a1 a2 ... an) applies the function fn to the arguments
a1, a2, ..., an. [stuff about macros etc. deleted]"

Most Common Lisp implementations (Allegro, Kyoto, Symbolics among
others), however, extend the semantics by saying that if fn evaluates
to a symbol, then the *global* (yuch!) function definition of that symbol is
used. This causes a great deal of confusion, as can be seen from the
ongoing discussion. Specifically, some of the examples given by
Richard Billington work only because of this hack. (Please do not
understand me wrong: I can understand the reasoning behind it, it
just gives my schemy mind the shivers!)

>>>>> On 1 Feb 90 20:11:05 GMT, bu...@pravda.gatech.edu (Richard Billington) said:
buff> (defun foo (x)
buff> (flet ((hi () (print "hi there")) ;same for labels
buff> (bye () (print "good-bye")))
buff> (funcall x)))

buff> and then got an error (that the function hi is undefined) when I
buff> tried the following:

buff> (foo 'hi)

Because funcall got the symbol 'hi' as the first argument, and didn't
find a global function definition for it.

buff> Whereas the following works fine:

buff> (defun hi () (print "hi there"))
buff> (defun foo (x) (funcall x))
buff> (foo 'hi) => "hi there"

Because this time there is a global function definition.

buff> (defun foo1 ()
buff> (flet ((hi () (print "hi there")) ;same for labels
buff> (bye () (print "good-bye")))
buff> (funcall 'hi)))

buff> (defun foo2 ()
buff> (flet ((hi () (print "hi there")) ;same for labels
buff> (bye () (print "good-bye")))
buff> (funcall #'hi)))

buff> foo2 works, foo1 doesn't. Now consider

Same thing here, foo1 does not find a global function definition. foo2
works, because "within the body of the flet form, function names
matching those defined by flet refer to the locally defined function
rather than to the global definitions of the same name" (CLtL).

buff> (defun foo3 (x)
buff> (let ((hi #'(lambda () (print "hi there")))
buff> (bye #'(lambda () (print "hi there"))))
buff> (funcall x)))

buff> This does work.

I got an error message from this (using Allegro CL 3.0.3). I suspect
that you had a global function called 'hi', and everything works as
before.

The thing that bothers my puritan mind here, is that somehow the
distinction between functions and symbols is blurred. In Scheme
everything is clear: a procedure is a procedure and a symbol is a
symbol. Once you introduce special treatment for some data types, you
get confusion because the language is no more logical. One thing that
surprises me is that CLtL does specify treatment for both functions
and symbols when given as arguments to apply (with the same semantics
as discussed before) but not for funcall.

I must say that this whole thing has really made me feel bad about CL.
Previously all I had against CL was it sheer size, but this funcall
stuff has really pissed me off. Using global function bindings seems
to me to violate all the nice rules of lexical scoping. To me it is
simply a dirty hack.

Moreover, the treatment of functions with all the special forms and
procedures seems to imply that functions in CL are not really first
class citizens, because one has to go thru a *lot* of trouble when
passing them around.

--
Pertti Kellom\"aki (TeX format) # These opinions are mine,
Tampere Univ. of TeXnology # ALL MINE !
Software Systems Lab # (but go ahead and use them, if you like)

Harley Davis

unread,
Feb 2, 1990, 8:24:33 AM2/2/90
to

> > interpreted as a variable. Erann Gat made the mistake of calling
> > these two interpretations the symbol-function and symbol-value
> > when those terms are properly applied only to symbols (acting
> > as global variables and function names). Local variables and
> > function names don't have symbol-values or symbol-functions in
> > that sense.
>
> I want to thank Jeff Dalton for coming to my defense. However, the
> above is totally incorrect (said with a smile). Temporary variables
> do have value and function bindings. That is why there are LET and
> FLET forms in CL. For example:
>
> (flet ((x (x) (+ x x)))
> (let ((x 1))
> (x x)))

The above is totally incorrect (:^)). Jeff correctly pointed out that
lexically-scoped variables do not, properly speaking, have
symbol-values or symbol-functions, because these variables, despite
all appearances, are not symbols. Special variables, on the other
hand, are symbols, to which symbol-function and symbol-value are
applicable. The non-symbolhood of lexical variables permits nifty
compiler optimizations.

The following code is erroneous unless x has been proclaimed special:

(flet ((x (x) (+ x x)))
(let ((x 1))

(list (symbol-function x) (symbol-value x))))

[ref. CLtL edition 1 p. 90]

-- Harley

------------------------------------------------------------------------------
Harley Davis internet: da...@ilog.fr
ILOG S.A. uucp: ..!mcvax!inria!davis
2 Avenue Gallie'ni, BP 85 tel: (33 1) 46 63 66 66
94253 Gentilly Cedex
France

Eric Muehle

unread,
Feb 2, 1990, 1:53:54 PM2/2/90
to

I stand corrected, and I apologize for my careless use of the terms
symbol-value and symbol-function. Nevertheless, I stand by the
assertion that identifiers in Common Lisp, be they local or global,
have two bindings, a value binding and a function binding, and that
this is the reason for the existence of an explicit FUNCALL function,

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


that is, to enable one to call a function stored in an identifier's
value slot.

I also reaffirm my position that multiple bindings cause a great deal of
confusion!

-Erann

What about this:

(funcall #'(lambda (x) (1+ x)) 10)

I am passing a function to FUNCALL, not an identifier. Being able to
call *functions* is the reason for the existence of FUNCALL. If there
was no FUNCALL then you can kiss all of your :test, :key, and any other
keywords that expects a FUNCTION for an argument goodbye.

ERIC MUEHLE

--
Eric Muehle (require :standard-disclaimers)
Boeing Aerospace and Electronics usenet: {world}!uw-beaver!ssc-vax!muehle
Seattle, WA arpanet: ssc-vax!mue...@beaver.cs.washington.edu

Richard Billington

unread,
Feb 2, 1990, 10:29:27 AM2/2/90
to
In article <PK.90Fe...@kaarne.tut.fi> p...@tut.fi (Kellom{ki Pertti) writes:
>buff> (defun foo3 (x)
>buff> (let ((hi #'(lambda () (print "hi there")))
>buff> (bye #'(lambda () (print "hi there"))))
>buff> (funcall x)))
>
>buff> This does work.
>
>I got an error message from this (using Allegro CL 3.0.3). I suspect
>that you had a global function called 'hi', and everything works as
>before.

Quite right. This was the only thing that really confused me, and it
was sloppy investigating on my part.

>Previously all I had against CL was it sheer size, but this funcall
>stuff has really pissed me off. Using global function bindings seems
>to me to violate all the nice rules of lexical scoping. To me it is
>simply a dirty hack.

Hmmm, I'm not so sure it violates lexical scoping. Now that you've pointed
out my error (in the above), it seems to me the behaviour observed in all
of my examples is quite consistant with lexical scoping: Within the function
definition, the local variable can be referenced with no problem. However,
if (as in my example) I try to reference a (dare I say) symbol which is
defined within the scope of the function I'm calling, I can't. Why? because
the name of the symbol in the calling environment (although identical in
print) is different from the name in the internal environment. The only
place where one must remember that local variables are not symbols is
in the case of (funcall 'x) because if x really was a symbol it would still
be hanging around and hence its functional definition would be available.
This, however, does not violate lexical scoping.

>Moreover, the treatment of functions with all the special forms and
>procedures seems to imply that functions in CL are not really first
>class citizens, because one has to go thru a *lot* of trouble when
>passing them around.

Whoever claimed that functions were first class citizens in any other lisp
than scheme - I thought that was the single biggest reason for bringing
scheme into existance: to have a clean implementation of the lambda calculus,
which lisp is NOT (even McCarthy agrees - making functions second class
citizens was a mistake).

>Pertti Kellom\"aki (TeX format) # These opinions are mine,
> Tampere Univ. of TeXnology # ALL MINE !
> Software Systems Lab # (but go ahead and use them, if you like)

Richard Billington (bu...@pravda.gatech.edu)

Erann Gat

unread,
Feb 2, 1990, 12:05:05 PM2/2/90
to
In article <PK.90Fe...@kaarne.tut.fi>, p...@tut.fi (Kellom{ki Pertti) writes:
> Most Common Lisp implementations (Allegro, Kyoto, Symbolics among
> others), however, extend the semantics [ of FUNCALL ]

> by saying that if fn evaluates
> to a symbol, then the *global* (yuch!) function definition of that symbol is
> used.

This is not an extension. On page 32 of CLtL it says, "A symbol may serve
as a function; an attempt to invoke a symbol as a function causes the
contents of the symbol's [global] function cell to be used."

BTW, thanks to Jeff and Sandra for setting me straight on the distinction
between symbols and local indentifiers. I really was confused on this
point!

E.

Erann Gat

unread,
Feb 2, 1990, 12:28:24 PM2/2/90
to
In article <22...@papaya.bbn.com>, ba...@bbn.com (Hunter Barr) writes:
> You wouldn't want
> to (UN-DEFVAR *PRINT-BASE*) would you? Now that *would* cause some
> problems.

I see your point. I guess my real gripe is that there is no way to
guarantee that a given variable is lexically scoped. I would like
to be able to do something like:

(let ((x 1)) (declare (lexical x)) ...

but CL has no such declaration. Granted, if you use the star convention
(and everyone else on your Lisp machine uses it too) then you probably
won't have problems. (This 'solution' is strongly reminiscent of the
FORTRAN convention of having all variables beginning with I,J,K,L,M or
N be integers.) However, the way things stand, one careless mistake or
ignorant user can require a LONG time to fix. (One day long ago I
typed (defvar x 1) as part of a quick experiment on a TI Explorer
and for the next few days no one could understand why their code
suddenly didn't work. Then someone rebooted the machine and all the
problems mysteriously vanished.)

E.

Mark Johnson

unread,
Feb 2, 1990, 2:45:12 PM2/2/90
to
g...@robotics.Jpl.Nasa.Gov writes:

> I guess my real gripe is that there is no way to
> guarantee that a given variable is lexically scoped.
> I would like to be able to do something like:
>
> (let ((x 1)) (declare (lexical x)) ...

I agree --- except that I think CL should be modified
so that all variables' values are determined using the
rules of lexical scoping, unless the variable reference
i explicitly identified as being dynamically scoped:
perhaps by using forms such as (dynamic x) or (special x).
(This is in addition to declaring the variable special
with defvar). Syntactic sugar for these forms could
easily be devised --- perhaps #*x could expand to
(dynamic x) or whatever?

Mark

Dorai Sitaram

unread,
Feb 4, 1990, 6:49:32 PM2/4/90
to
In article <16...@skye.ed.ac.uk> je...@aiai.UUCP (Jeff Dalton) writes:
$In article <3...@forsight.Jpl.Nasa.Gov> g...@robotics.Jpl.Nasa.Gov (Erann Gat) writes:
$>In article <1990Jan29.2...@hellgate.utah.edu>, sandra%defun.utah.edu@cs.
$>utah.edu (Sandra J Loosemore) writes:
$>> Scheme has a FUNCALL operation with exactly the same *semantics* as
$>> that in Common Lisp. It does, however, have different syntax, which
$>> most people would probably agree is less complicated.
$
$I'm not sure it's fair to say FUNCALL is just syntax, because FUNCALL
$is not restricted to appearing as the car of a function call. FUNCALL
^^^^^^^
$is a function, and Scheme does not have such a function. Since the
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
$original quesiton was "why is FUNCALL a function?", this is a relevant,
$although minor, point.
$
$I think it's true that most people now prefer the Scheme approach; but
$it depends, in part, on what sort of code is involved. When a lot of
$FUNCALLs are needed, they can make code look cluttered and hard to
$read. But when they're rare, they can act as a useful sign that
$something unusual is happening.
$
$>Scheme has a FUNCALL only insofar as its semantics for calling functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
$>are the same as the semantics of funcall. Scheme does not have a
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
$>function which does what FUNCALL does.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
$
$I agree (see above).

I saw the above rather by accident, so what I say here might take
something out of context. Disclaimer done, I don't see how someone
can claim that Scheme doesn't have a _funcall_ function (procedure).
Surely you don't just mean that the language standard doesn't mention
_funcall_? For _funcall_ is easily retrieved as:

(define funcall (lambda (f . z) (apply f z)))

So what am I missing?

--dorai
--
-------------------------------------------------------------------------------
It may be that the gulfs will wash us down;
It may be we shall touch the Happy Isles.
-------------------------------------------------------------------------------

Jeff Dalton

unread,
Feb 5, 1990, 11:33:36 AM2/5/90
to
In article <45...@brazos.Rice.edu> do...@titan.rice.edu (Dorai Sitaram) writes:
>In article <16...@skye.ed.ac.uk> je...@aiai.UUCP (Jeff Dalton) writes:

>$I'm not sure it's fair to say FUNCALL is just syntax, because FUNCALL
>$is not restricted to appearing as the car of a function call. FUNCALL
> ^^^^^^^
>$is a function, and Scheme does not have such a function. Since the
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>$original quesiton was "why is FUNCALL a function?", this is a relevant,
>$although minor, point.

>I saw the above rather by accident, so what I say here might take


>something out of context. Disclaimer done, I don't see how someone
>can claim that Scheme doesn't have a _funcall_ function (procedure).
>Surely you don't just mean that the language standard doesn't mention
>_funcall_? For _funcall_ is easily retrieved as:
>
> (define funcall (lambda (f . z) (apply f z)))
>
>So what am I missing?

Presumably you don't think there's *no* difference between Scheme and
Common Lisp on this point.

What you seem to be missing is the difference between "unlike Common
Lisp, Scheme doesn't have a function called FUNCALL" and "FUNCALL
can't be defined in Scheme". Maybe that's not quite what you're
missing, but you do seem to be replying to the second claim rather
than the first.

I suppose I am just saying the Scheme Report doesn't mention funcall,
but note that I did say it was a minor point. Nonetheless, there are
some practical consequences. That the language standard doesn't
mention funcall means that the user has to define it (if the user
wants it at all, which in Scheme is unlikely).

-- Jeff

Jeff Dalton

unread,
Feb 5, 1990, 11:35:14 AM2/5/90
to
> However, the way things stand, one careless mistake or
>ignorant user can require a LONG time to fix. (One day long ago I
>typed (defvar x 1) as part of a quick experiment on a TI Explorer
>and for the next few days no one could understand why their code
>suddenly didn't work. Then someone rebooted the machine and all the
>problems mysteriously vanished.)

Special variables aren't the only thing like this. Try redefining CAR
or LIST, for example.

Jeff Dalton

unread,
Feb 5, 1990, 11:41:01 AM2/5/90
to
In article <19...@mephisto.UUCP> bu...@pravda.UUCP (Richard Billington) writes:
>Whoever claimed that functions were first class citizens in any other lisp
>than scheme - I thought that was the single biggest reason for bringing
>scheme into existance: to have a clean implementation of the lambda calculus,
>which lisp is NOT (even McCarthy agrees - making functions second class
>citizens was a mistake).

I would say functons are 1st class in Common Lisp. They can be passed
as arguments, returned as results, assigned to variables, included in
data structures and have indefinite lifetimes just like, say, lists.
What more is needed? OK, they can't be read and printed, but they
can't in Scheme either.

(Note, though, that in CLtL '84 functions needn't be a distinct data
type -- eg, they might be lists. I'm assuming that this will change.)

-- Jeff

Jeff Dalton

unread,
Feb 5, 1990, 11:54:20 AM2/5/90
to
In article <69...@ilog.UUCP> da...@ilog.UUCP (Harley Davis) writes:
>The following code is erroneous unless x has been proclaimed special:
>
>(flet ((x (x) (+ x x)))
> (let ((x 1))
> (list (symbol-function x) (symbol-value x))))
>
>[ref. CLtL edition 1 p. 90]

Um, isn't it erroneous even if X _has_ been proclaimed special?

For instance, in

(list (symbol-function x) (symbol-value x))))

both SYMBOL-FUNCTION and SYMBOL-VALUE will complain because they're
being called on the number 1. That will happen even if X is special.
We might try quoting X, but SYMBOL-FUNCTION will still complain,
because special declarations don't affect function bindings.

-- Jeff

Erann Gat

unread,
Feb 5, 1990, 1:37:37 PM2/5/90
to
In article <45...@brazos.Rice.edu>, do...@titan.rice.edu (Dorai Sitaram) writes:
>
> I saw the above rather by accident, so what I say here might take
> something out of context. Disclaimer done, I don't see how someone
> can claim that Scheme doesn't have a _funcall_ function (procedure).
> Surely you don't just mean that the language standard doesn't mention
> _funcall_? For _funcall_ is easily retrieved as:
>
> (define funcall (lambda (f . z) (apply f z)))
>
> So what am I missing?

What you (and Eric Meuhler, author of article 1753) are both missing
is about twenty articles of discussion which preceeded the postings
to which you reply. In fact, that the Scheme language standard
does not mention FUNCALL is EXACTLY what I meant, and if you had gone
back and read the reference articles (or sent me E-mail) you could have
found this out without broadcasting the fact that you hadn't done your
homework.

E.

Barry Margolin

unread,
Feb 9, 1990, 1:37:08 AM2/9/90
to
In article <ALMS.90Ja...@brazil.cambridge.apple.com> al...@cambridge.apple.com (Andrew L. M. Shalit) writes:
>Turning off a special proclamation would involve going through all the
>compiled functions in the world which reference the variable, and
>changing them to treat the variable as lexical.

This is not necessary. Just as DEFVAR doesn't find previous references to
the variable and change them from lexical to special, there's no need for
UNDEFVAR to go back and change them from special to lexical. There's
precedent for this: (proclaim '(notinline <function-name>)) doesn't
de-inline previous invocations of the function.

Of course, since we're describing an implementation-dependent extension, we
can't really say for sure how it would behave. If an implementation wanted
to provide the semantics you describe, and wanted to make it efficient, it
could keep back pointers. However, I'm not sure why you'd want those
semantics. Consider the following code:

(defvar *foobar*)

(defun fun1 (arg)
(let ((*foobar* (* arg arg)))
(fun2))

(defun fun2 ()
(print *foobar*))

(undefvar *foobar*)

The point of the DEFVAR/UNDEFVAR is to make *FOOBAR* special only in the
functions FUN1 and FUN2; they're equivalent to wrapping all the functions
in a (locally (declare (special *foobar*)) ...).

In general, changing declarations should not affect previously-defined
functions.

Jeff Dalton

unread,
Feb 10, 1990, 12:23:30 PM2/10/90
to
In article <ALMS.90Ja...@brazil.cambridge.apple.com> al...@cambridge.apple.com (Andrew L. M. Shalit) writes:
>In article <16...@skye.ed.ac.uk> je...@aiai.ed.ac.uk (Jeff Dalton) writes:

> However, nothing says an implementation can't provide some way to
> turn off a SPECIAL proclamation (which is how DEFVAR makes the
> variable special). There just isn't a standard way to do it.

>Turning off a special proclamation would involve going through all the
>compiled functions in the world which reference the variable, and
>changing them to treat the variable as lexical.

I'd call that "undoing the effects of the DEFVAR". In any case, I
didn't intend it to be a necessary part of "turn off". The variable
could be made nonspecial [ie, no longer proclaimed special] without
undoing all the effects of it having once been special.

A fairly similar case would be that of redefining a macro as a
function. Many implementations let you do that but don't try to
make the world be as if the macro had never been defined.

>Some implementations might be able to backpatch the functions, but
>others would probably need to recompile them.

Here too it's useful to think of the macro case. A number of
implementations re-expand macro calls each time they're evaluated by
the interpreter. (Or they cache expansions and re-expand only if the
macro has been redefined.) Likewise, they re-determine whether or not
a variable is special each time the interpreter evaluates a binding
form. So most of the effects are undone, in effect, just by the way
the interpreter works. It's only when we turn to compiled code that
things like backpatching and recompilation become necessary. Most
implementations (as far as I know) don't automatically undo the
effects of canceled special proclamations, or of macros redefined as
function, in compiled code.

-- Jeff

Paul Fuqua

unread,
Feb 16, 1990, 3:05:53 PM2/16/90
to

Date: Monday, January 29, 1990 1:11pm (CST)
From: gjc at paradigm.com
Subject: Re: FUNCALL question, fun facts
Newsgroups: comp.lang.lisp

(1) In the MIT CADR or LMI LAMBDA lispmachine (FUNCALL F X) and (F X) compiled
into *exactly* the same machine instructions.
(2) The case (FUNCALL F X) where F was a local variable was very slightly,
but measurably FASTER than the case of (F X) where F was a "global"
(3) Symbolics and then later Texas Instruments improved on the instruction
set such that (FUNCALL F X) and (F X) were indeed different, resulting
in some extra overhead for the FUNCALL case, although it is very
difficult to measure the difference.

Regarding the TI Explorer, I beg to differ. I wrote the Release 3
function-calling microcode, which is substantially unchanged through the
current release, so I have some idea what I'm talking about.

There is only one batch of CALL instructions, used identically by both
(FUNCALL F X) and (F X). A CALL will be slightly faster if the function
is a local variable, an argument, or popped from the stack, because
stack references don't involve an external memory access. If the
function is global, the additional overhead is two memory references.
The additional overhead of a lexical closure is mostly just extracting
the environment structure and setting it up in a local variable.

Paul Fuqua p...@csc.ti.com
{smu,texsun,cs.utexas.edu,rice}!ti-csl!pf
Texas Instruments Computer Science Center
PO Box 655474 MS 238, Dallas, Texas 75265

0 new messages