2
votes

There seems to be a number of different ways of referring to a function in Common Lisp:

  1. via symbol, where the symbol appears (unquoted) as the car of a form as in (1+ 2) => 3, or in a functional argument position as in (mapcar '1+ '(1 2 3)) => (2 3 4);

  2. via function object, where the (interpreted or compiled) function object can appear in functional argument position as in (mapcar #'1+ '(1 2 3)) => (2 3 4) or (mapcar (symbol-function '1+) '(1 2 3)) => (2 3 4), but not as the car of a form as in (#'1+ 2) => error or ((symbol-function '1+) 2) => error;

  3. via lambda expression, where the lambda expression appears as the car of a lambda form as in ((lambda (x) (1+ x)) 2) => 3, or in a functional argument position as in (mapcar (lambda (x) (1+ x)) '(1 2 3)) => (2 3 4) [However, the Hyperspec does not recognize lambda expression as a "function designator"].

Of these three "ways", to me the first seems somewhat out of place, because it seems to complicate the fundamental guideline that Common Lisp operators evaluate their arguments only once. And if, in the example above, '1+ is evaluated, it would produce the symbol 1+, not the function named by the symbol. In this case, there must be an additional evaluation, possibly symbol-function, to get at the function object. Evidently, this is simply a convenience, but it seems to break with consistency. (The consistent form #'1+ is almost as simple.) My question is 'Are there any examples where using a symbol for a function is required (other than as the car of a form--although even this is not required, given lambda expressions), so that you cannot fully avoid expressions as in item 1 above?.

1

1 Answers

7
votes

Symbols as names for objects: Designators

Often symbols are names for objects and can be used instead of these objects.

The concept that something like a symbol (or a string, a character) may stand for something else is called in Common Lisp a designator.

Some example for designators:

Function designator:

(funcall 'list 1 2 3)
<->
(funcall (symbol-function 'list) 1 2 3)

Class, or symbol that names a class:

(make-instance 'my-class)
<->
(make-instance (find-class 'my-class))

Package designator:

(package-use-list 'cl-user)
<->
(package-use-list (find-package 'cl-user))
<->
(package-use-list "CL-USER")

String designator:

(string-upcase 'f)
<->
(string-upcase (symbol-name 'f))
<->
(string-upcase #\f)

The first argument to FUNCALL thus is not defined as a function, but as a function designator. In this case either a function object or a symbol. If it is a symbol, then the global symbol function is retrieved.

Historically Lisp uses symbols as names for various kinds of objects. This is less prominent in some later dialects or derived languages.

function object vs. calling a named function vs. calling a symbol function

...(funcall (function foo) 1 2 3)...
...(funcall #'foo 1 2 3)...

Above calls the lexical function named foo. If there is no lexical function foo, it calls the symbol function of foo. The Lisp file compiler may assume that this is the same named function in the same file.

...(foo 1 2 3)...

Above calls the lexical function named foo. If there is no lexical function foo, it calls the symbol function of foo. The Lisp file compiler may assume that this is the same named function in the same file.

...(funcall 'foo 1 2 3)...

Above calls the global symbol function of foo. Thus there will be a lookup through the symbol.