funcall
by Bruce Butterfield » Sun, 30 Jan 2005 04:27:47 GMT
Why does funcall allow either a symbol or a function as it's first
argument? Is this a convenience or is there a more interesting
rationale? It seems odd that
(funcall '+ 1 2 3)
and
(funcall #'+ 1 2 3)
both return the same value. It seems inconsistent to this noob.
The hyperspec says:
funcall applies function to args. If function is a symbol, it is
coerced to a function as if by finding its functional value in the
global environment.
Re: funcall
by David Sletten » Sun, 30 Jan 2005 04:51:23 GMT
I think 'superfluous' would be more appropriate than 'inconsistent'.
However, it's not superfluous as I will show.
The reason for this behavior is that not every function exists in the
global environment:
(defun pung () 'foo)
(flet ((pung () 'bar))
(print (funcall 'pung))
(print (funcall #'pung)))
This outputs:
FOO
BAR
The second FUNCALL is given the local function object corresponding to
PUNG within the FLET context. The first one has to find the global
function associated with the symbol PUNG, i.e., via (SYMBOL-FUNCTION 'PUNG).
This type of behavior (shadowing functions) is probably not used very
often. However, bear in mind when using FLET/LABELS that FUNCALL needs
function objects (#') not names (symbols) to access those local
functions. A common mistake would be something like:
(dolist (f '(pung foo bar))
(funcall f ...))
Instead you might need:
(dolist (f (list #'pung #'foo #'bar))
(funcall f ...))
David Sletten
David Sletten
Re: funcall
by Marco Baringer » Sun, 30 Jan 2005 04:53:04 GMT
"Bruce Butterfield" < XXXX@XXXXX.COM > writes:
it's just different. funcall can be passed either the name of a
function, in which case a lookup is done at evecution time in the
global name space, or a function object (what #'+ returns).
condsider this:
(defun foo () 'global)
(flet ((foo () 'local))
(list (funcall #'foo) (funcall 'foo)))
==>
(LOCAL GLOBAL)
and then this:
(defun foo () 'first)
(defvar sharp-f #'foo)
(defvar quote-f 'foo)
(defun foo () 'second)
(list (funcall sharp-f) (funcall quote-f))
==>
(FIRST SECOND)
hope this helps.
--
-Marco
Ring the bells that still can ring.
Forget the perfect offering.
There is a crack in everything.
That's how the light gets in.
-Leonard Cohen
Re: funcall
by jtdubs » Sun, 30 Jan 2005 05:14:11 GMT
CL-USER 1 > (defun foo (x y) (+ x y))
FOO
CL-USER 2 > (flet ((foo (x y) (* x y)))
. (values (funcall #'foo 3 4)
. (funcall 'foo 3 4)))
12
7
The #' is syntactic-sugar for (function ...). And ' is sugar for
(quote ...). So, your choice is really between:
(funcall (function foo) ...)
and
(funcall (quote foo) ...)
Here's a snipit of the CLHS entry for the "function" special operator:
( http://www.**--****.com/ #function)
"The value of function is the functional value of name in the current
lexical environment."
And, as you quoted from the CLHS for funcall, if you pass a symbol you
get the current binding in the global environment.
So, #' gives you the lexical binding and ' gives you the global
binding. So, #' will notice lexical definitions defined by flet and
labels, but ' won't.
I'm not the best person to explain this next bit. I'm sure Paul or
Duane or someone can give you a much better worded explanation, but...
Basically, any lexical binding you have in your code, whether via let
or flet or labels, has it's name thrown out by the compiler. There is
no reason to keep it around. If you define some variable bindings with
let, then references to those variables within the let just get
compiled to reference the binding itself. It doesn't need to know that
it was called "x" or "foo" at run-time. Same with flet and labels.
So, when the compiler see's a (funcall #'foo ...) inside of a (flet
((foo ...)) ...) it just compiles the funcall to call the function
defined by the flet. It doesn't matter whether it was called foo or
not after it is compiled.
However, if you say (funcall 'foo ...), that means that funcall has to,
at run-time, find the current function binding for the symbol "foo".
As the lexical bindings have lost their names, it has no choice but to
find the global binding as defined by defun.
I hope this makes some sense. If I have a piece of that wrong or
worded poorly I hope someone will jump in and set me straight.
Justin Dubs
Re: funcall
by Duane Rettig » Sun, 30 Jan 2005 06:34:52 GMT
"jtdubs" < XXXX@XXXXX.COM > writes:
[ ... ]
Looked fine to me.
--
Duane Rettig XXXX@XXXXX.COM Franz Inc. http://www.**--****.com/
555 12th St., Suite 1450 http://www.**--****.com/
Oakland, Ca. 94607 Phone: (510) 452-2000; Fax: (510) 452-0182
Re: funcall
by Barry Margolin » Sun, 30 Jan 2005 11:34:26 GMT
In article < XXXX@XXXXX.COM >,
(defun some-function ()
'old-definition)
(defvar *func1* 'some-function)
(defvar *func2* #'some-function)
(defun some-function ()
'new-definition)
(funcall *func1*) => NEW-DEFINITION
(funcall *func2*) => OLD-DEFINITION
So if you want to save away function information, and have it track
redefinitions, you need to use the name rather than the function object.
--
Barry Margolin, XXXX@XXXXX.COM
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Re: funcall
by Steven M. Haflich » Tue, 01 Feb 2005 09:35:59 GMT
The basic argument of the above paragraph concerning lexical and global
function namespaces is incorrect, but some details are bogus.
Specifically, there is no guarantee that the code will resolve the
global function binding at run time. ANS 3.2.2.3 Semantic Constraints
gives specific license for the compiler to make compile time assumptions
about calls to "a named function that is defined in the same file." It
is less clear whether the compiler is allowed to inline functions from
other files, absent an inline declaration. It is also unclear whether
this "same file" clause might have been rewritten as "same
with-compilation-unit" when that macro was added to the language. I
don't remember whether that was specifically considered.
But I wanted to caution against equating the global environment with
run-time lookup. The two have little to do with one another.
Re: funcall
by Barry Margolin » Tue, 01 Feb 2005 12:13:40 GMT
In article <P3fLd.18484$ XXXX@XXXXX.COM >,
The only time I think this could make a difference would be if you
actually put the quoted function name in the FUNCALL form. Except
perhaps as a result of macro expansion, this seems like a silly thing to
do, since
(funcall 'foo ...)
is essentially the same as
(foo ...)
unless there's a local function binding of FOO in scope. FUNCALL is
virtually always called using a computed function object or name. And
if the computation returns a symbol, its global function binding has to
be looked up at run-time.
--
Barry Margolin, XXXX@XXXXX.COM
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Similar Threads:
1.Scheme substitute for FUNCALL?
Hi all,
In Common Lisp I can cleanly invoke a function upon a fixed set of
arguments:
(funcall (read) 1 2 3)
If I evaluate this and type in `list', (1 2 3) is returned. If I type in
`+', 6 is returned, etc.
What's the Scheme idiom for this, please?
Regards,
Adam
2.An example on the FUNCALL page
On the FUNCALL page of the HS the following example
appears:
(flet ((cons (x y) `(kons ,x ,y)))
(let ((cons (symbol-function '+)))
(funcall #'cons
(funcall 'cons 1 2)
(funcall cons 1 2))))
=> (KONS (1 . 2) 3)
On SBCL it causes an error. Is the code correct or is
redefining cons undefined behaviour ?
Would the point of the example be illustrated by the
following code ?
(defun new-cons (x y) (cons x y))
(flet ((new-cons (x y) `(kons ,x ,y)))
(let ((new-cons (symbol-function '+)))
(funcall #'new-cons
(funcall 'new-cons 1 2)
(funcall new-cons 1 2))))
=> (KONS (1 . 2) 3)
3.Question re CL need of funcall ?
After being exposed to Scheme : through converting SICP code to Common
Lisp
I wonder why CL decided to use funcall .
For example
If fn is an function as argument , like
(defun baz (fn x)
(funcall fn x))
couldn't compiler insert funcall when it sees fn after opening bracket
so this would be the same as above :
(defun baz (fn x)
(fn x))
(baz #'1+ 2)
4.Undefined function (SETF FUNCALL)
Can someone suggest a way to avoid this compiler error?
I'd like to refactor the following dual WHEN expressions
which only differ by swapping RIGHT and LEFT everywhere they
occur.
(when (member (name left) (left-instances ic) :test #'eq)
(push (name left) (right-instances ic))
(setf (left-instances ic)
(delete (name left) (left-instances ic) :test #'eq)))
(when (member (name right) (right-instances ic) :test #'eq)
(push (name right) (left-instances ic))
(setf (right-instances ic)
(delete (name right) (right-instances ic) :test #'eq)))
I've changed the forms to the following:
(swap-connected-instances ic left #'left-instances
#'right-instances)
(swap-connected-instances ic right #'right-instances
#'left-instances)
And i've written the function:
(defun swap-connected-instances (ic left left-fun right-fun)
(when (member (name left) (funcall left-fun ic) :test #'eq)
(push (name left) (funcall right-fun ic))
(setf (funcall left-fun ic)
(delete (name left) (funcall left-fun ic) :test #'eq))))
However, the problem is that (SETF (FUNCALL ...)) causes a compiler
error. :-(
Undefined function (SETF FUNCALL) as the argument to FUNCTION
Does this mean the only way to refactor this is by using a macro
instead of a function?
I'd like to make it a function because i'm
profiling these functions seperate from the function calling them.
-jim
5.Funcalling from flet
Why doesn't this work (except when foo and bar are defined globally (with defun))?
(defun process-command-list (list)
(flet
((foo ()
(print "foo"))
(bar ()
(print "bar")))
(dolist (fun list)
(funcall fun)))) => process-command-list
(process-command-list '(foo bar bar)) => ...error...
Also, why does
(defun dummy-function () 'top-level) => DUMMY-FUNCTION
(flet ((dummy-function () 'shadow))
(eq (funcall #'dummy-function)
(funcall 'dummy-function))) => nil
work the way it works (example from the Hyperspec).
6. why funcall is needed in things like ((foo) 10)
7. MAPCAR, FUNCALL & APPLY usage
8. (funcall #'or my-list)