Lone Learner
Lone Learner

Reputation: 20628

Difference between #'callee and 'callee in Common Lisp

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:

  1. What's the difference between the #'callee syntax and the 'callee syntax?
  2. How is it that funcall is able to invoke the callee in both cases successfully?
  3. Is there any best practice or pros and cons associated with both syntaxes due to which one is preferred over another?

Upvotes: 0

Views: 131

Answers (2)

Gwang-Jin Kim
Gwang-Jin Kim

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

ptb
ptb

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

Related Questions