The #' in common lisp
Asked Answered
A

2

17

In chapter 3 of Practical Common Lisp book there's an example of a SQL-like select and where functions. Here's a simplified version of it:

(defun where (x) 
   #'(lambda (item)
     (> item x)))

and it is used like this:

(remove-if-not (where 2) (list 1 2 3 4))

Earlier in the book it is explained that the #' sequence is used to state that it is followed by a function name, rather than a variable that requires evaluation. I don't understand why it's needed here. I tried implementing the where function without it and it worked as well:

(defun where (x) 
   (lambda (item)
     (> item x)))

I tried googling for it, and, as you can imagine, with such a sequence of characters it wasn't a very fruitful search. And I don't know the name of this thing. Is there any particular reason why it's needed in the above code?

Accusative answered 24/12, 2012 at 13:21 Comment(3)
see https://mcmap.net/q/174451/-emacs-elisp-what-is-the-hash-pound-number-sign-octothorp-symbol-used-for/309483Scleroma
found with this google queryScleroma
nowadays, you can find this question with "lisp #'" on GoogleMcmurry
S
17

This is the precise page in Hyperspec which deals with the standard macro character "sharp" followed by "single quote".

To make it simple, this reader macro expands to enclose the following form into (function <form>) s-expression. This effectively tells the parser that the form is callable.

lambda is a macro, which generates the code, which already contains the (function <form>), but historically and for consistency, the alternative form, which is obtained from the reader macro with sharp + quote, is often used too.

Here's Writing lambda expressions in common lisp (another StackOverflow question) which covers in-depth the particular case of (lambda <form>)

Sticktight answered 24/12, 2012 at 13:42 Comment(1)
Specifically, #'(lambda () nil) is NOT a macro invocation, but a function literal and (lambda () nil) invokes a macro-expander that expands to #'(lambda () nil).Arduous
D
7

Note: *print-pretty* is NIL for these examples.

(defun where (x) 
  #'(lambda (item)
      (> item x)))

In above function where you are creating an anonymous function and you are returning it as a closure (the function plus variable binding for X). Since you are returning it as a value, you have to write (FUNCTION (LAMBDA ...)). #'(lambda ...) is a notation which is shorter, but results in the same - using the reader macro #':

CL-USER 74 > (read-from-string "#'(lambda (foo) (1+ foo))")
(FUNCTION (LAMBDA (FOO) (1+ FOO)))

You can also write:

(defun where (x) 
  (lambda (item)
    (> item x)))

During the definition of Common Lisp it has been added to be able to write above code. It is also identical to the (function (lambda ...)) form. In Common Lisp LAMBDA is macro, which expands into it:

CL-USER 75 > '(lambda (foo) (1+ foo))
(LAMBDA (FOO) (1+ FOO))

CL-USER 76 > (macroexpand '(lambda (foo) (1+ foo)))
(FUNCTION (LAMBDA (FOO) (1+ FOO)))
T

So, LAMBDA is a macro and when the evaluator sees it as in (lambda ...), it expands the form into a (function (lambda ...)) form, which then gets evaluated.

FUNCTION is a special form and when the evaluator sees it, it returns a function object - in the case of (function (lambda (foo) (1+ foo))) it returns the anonymous function as an object:

CL-USER 77 > (function (lambda (foo) (1+ foo)))
#<anonymous interpreted function 406000761C>

So you see that (function (lambda ...)) is the real s-expression notation to get a function object and both #'(lambda ...) (via a reader macro) or (lambda ...) (via a macro) are shorter notations in Lisp source code. It is unusual for a programmer to use the long form. Most (99.999%) use one of the shorter notations in source code.

Btw.: If the evaluator sees function enclosing a name of a function like this (function sin), then it looks up the function binding and returns the corresponding function object:

CL-USER 78 > (function sin)
#<Function SIN 4110083C6C>
Djerba answered 24/12, 2012 at 14:50 Comment(4)
When I tried to run your code in REPL I got slightly different results. # doesn't seem to be replaced with function. In particular (read-from-string "#'(lambda (foo) (1+ foo))") results in #'(LAMBDA (FOO) (1+ FOO)) and (macroexpand '(lambda (foo) (1+ foo))) results in #'(LAMBDA (FOO) (1+ FOO)). I'm using Lisp in a Box and Clozure Common Lisp.Accusative
@Max: When *print-pretty* is T, then it tries to print it that way. Set *print-pretty* to NIL and try again...Djerba
I just checked and print-pretty is nilAccusative
In CCL use also (setf *PRINT-ABBREVIATE-QUOTE* nil).Djerba

© 2022 - 2024 — McMap. All rights reserved.