Reputation: 20628
Here is my Common Lisp code:
(defun caller (f)
(format t "caller: f: ~a~%" f)
(funcall f 10))
(defun callee (x)
(format t "callee: x: ~a~%" x))
(caller #'callee)
(caller 'callee)
Here is the output I get with clisp
:
$ clisp foo.lisp
caller: f: #<FUNCTION CALLEE (X) (DECLARE (IN-DEFUN CALLEE)) (BLOCK CALLEE (FORMAT T callee: x: ~a~% X))>
callee: x: 10
caller: f: CALLEE
callee: x: 10
I want to know what is the difference between the syntax #'callee
and the syntax 'callee
.
Although with both syntaxes, I am able to pass the callee
to the caller
, the caller: f:
output seems to indicate that there is some subtle difference in both the syntaxes: #'callee
seems to refer to a function object but 'callee
seems to refer to just the function name.
Here are my questions:
#'callee
syntax and the 'callee
syntax?funcall
is able to invoke the callee
in both cases successfully?Upvotes: 0
Views: 131
Reputation: 9865
#'callee
expands to (function callee)
while 'callee
expands to (quote callee)
.
#'
looks up in the function name space. (Common Lisp is a 2-Lisp, meaning it has 2 separate namespaces which allows that a function can have the same name like a variable/data - Scheme/Racket is a 1-Lisp where function and variables share the same namespace - meaning sth with a specific name is either a function or a name for some other object).
'
doesn't look up anywhere but evaluates the following symbol name to itself a name.
funcall
looks up its arguments name in the function name space and returns the function assigned to it. If you do a normal function call (callee 10)
, the Lisp interpreter implicitely looks up callee
from the function namespace, because the first position in a list which gets executed is reserved for the function name. When functionnames are given as arguments, in other positions than the first, you have to apply funcall
or #'
on them first, so that the interpreter knows that this name it has to lookup in the function name space and not in the normal variable name space.
Try this:
(defun d (x) x) ;; declares a function d in the function name space
(setf d 1) ;; declares variable d in the variable name space
(list d #'d d #'d)
;; returns:
(1 #<FUNCTION D (X) (DECLARE (SYSTEM::IN-DEFUN D)) (BLOCK D X)> 1
#<FUNCTION D (X) (DECLARE (SYSTEM::IN-DEFUN D)) (BLOCK D X)>)
;; when `#'` is given, the d is looked up from the function name space,
;; without, d is looked up from the normal variable name space
(d d)
;; the first position d gets looked up from the function name space but
;; the argument d from the variable name space
;; since the function d is the identity function and variable d has the value 1,
;; this evaluates the identity function on 1, thus to
1
(d #'d) ;; now the argument `d` is looked up from the function name space
;; thereby returning a function:
#<FUNCTION D (X) (DECLARE (SYSTEM::IN-DEFUN D)) (BLOCK D X)>
Upvotes: 1
Reputation: 2148
The difference is largely one of how the function is looked up. If one passes a symbol to funcall
, it is looked up in the global (rather than lexical) environment. The relevant documentation is http://clhs.lisp.se/Body/f_funcal.htm. I've slightly modified the example from the docs:
(defun cons* (&rest rest)
(apply 'cons rest))
(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)
Upvotes: 1