funcall

lisp

funcall

Postby 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

Postby 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

Postby 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

Postby 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

Postby 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

Postby 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

Postby 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

Postby 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)



Return to lisp

 

Who is online

Users browsing this forum: No registered users and 38 guest