I’m not a Common Lisp expert and I’m also not a seasoned Lisp programmer, so I’m very happy to be corrected if I get things wrong, but this is my explanation to the best of my current knowledge and understanding:
To understand why Common Lisp has the '#
expression it is helpful to know that Common Lisp is a so called Lisp-2, which means that in Common Lisp you can have a variable that refers to a function and a value in the same scope at the same time.
See this Stack Overflow thread for more information and additional reading material: clojure - What is the difference between Lisp-1 and Lisp-2? - Stack Overflow
This also means that calling the lambdas in your second example won’t work, because defparameter doesn’t define a function:
CL-USER: (greet1)
("undefined function")
CL-USER: (greet2)
("undefined function")
Now in your example, how do we tell Lisp that we want the function of the name hi
? One way is to write (function hi)
but because this is long, there is the possibility to abbreviate this with the '#
notation (Sharpsign Single-Quote).
See the HyperSpec on this: CLHS: Section 2.4.8.2
Now why can you write a lambda expression with the #'
syntax in front of it?
In Common Lisp there are two ways to use lambda
:
- as a symbol
- as a macro
The “as a symbol” part basically means that if a compound form doesn’t start with a symbol but with an s-expression that starts with a lambda
symbol (lambda expression), then this lambda expression will be called as a function, which I think is a complicated way of saying that you can write ((lambda (x y) (+ x y)) 2 3)
and it will evaluate to 5
. To learn more about this I recommend reading up about forms and the evaluation model here: CLHS: Section 3.1.2.1.2
Now to use a lambda expression in a place where Lisp expects a function you need to tell Lisp that the lambda should be treated as a function, which you would usually do by wrapping it in a (function)
call. And we learned earlier that (function)
is equivalent to '#
.
From the HyperSpec:
(lambda lambda-list [[declaration* | documentation]] form*)
== (function (lambda lambda-list [[declaration* | documentation]] form*))
== #'(lambda lambda-list [[declaration* | documentation]] form*)
Or asking lisp about it:
CL-USER: (macroexpand '(lambda () 'hello))
#'(LAMBDA () 'HELLO)
Quoting from Stack Overflow:
FUNCTION is a special operator. It expects a function name or a lambda expression. Thus the name or the lambda expression are not evaluated. In fact lambda expressions can’t be evaluated at all. Inside FUNCTION
, the lambda expression is not a macro form and thus will not be expanded again. The purpose of FUNCTION
is to return the corresponding function object which is denoted by the name or by the lambda expression. It returns the function object as a value. With this special operator one can access the function object from global functions and lexical functions.
The discussions why some people prefer '#
to the macro sometimes go over my head (see comments here), but I think you can see both forms as equivalent for now. One thing to note is that the lambda
macro was initially not part of Common Lisp, so some old books might always use the Sharpsign Single-Quote form just because of that. (eg. On Lisp)