30

Q: When, if ever, is it useful to sharp-quote a lambda, and when, if ever, must we not sharp-quote a lambda?

People use lambdas in three ways:

  1. plain: (lambda (x) x)
  2. quoted: '(lambda (x) x)
  3. sharp-quoted: #'(lambda (x) x)

This SO thread discusses the three types, this SO thread explains why not to quote (NB: not sharp-quote) lambdas, and this SO thread also discusses the distinctions between quoting and sharp-quoting.

Now, the manual node on anonymous functions and the docstring for lambda note that lambdas are self-quoting:

A call of the form (lambda ARGS DOCSTRING INTERACTIVE BODY) is self-quoting; the result of evaluating the lambda expression is the expression itself. The lambda expression may then be treated as a function...

So, it appears that (lambda (x) x) and #'(lambda (x) x) are equivalent, but '(lambda (x) x) is not (most importantly, when byte-compiling).

It looks like one would rarely want to quote a lambda, but it's unclear to me when, if ever, we should, or should not, sharp-quote:

  • Is sharp-quoting a lambda simply a stylistic choice, or are there circumstances in which sharp-quoting is actually useful?
  • Are there circumstances in which we must not sharp-quote a lambda, that is, when doing so would alter the meaning of the code?
28

Once upon a time, the sharp quote was necessary for lambdas, now that's no longer the case.

So, it appears that (lambda (x) x) and #'(lambda (x) x) are equivalent, but '(lambda (x) x) is not (most importantly, when byte-compiling).

Yes. In fact, the first two are completely identical when evaluated. As described in the manual page you linked:

The following forms are all equivalent:

(lambda (x) (* x x)) 
(function (lambda (x) (* x x))) 
#'(lambda (x) (* x x))

Other than trying to support Emacs versions from two decades ago, there's never a reason to sharp quote a lambda.

So don't.


As a sidenote:

  • Hard quoting a lambda (with ') does make a difference, it prevents byte compilation. I can't think of a scenario where that's useful, but who knows.

  • The backtic is the only quote that's genuinely useful with lambdas, but only if you're not using lexical binding for some reason.

  • Consider adding a link to the Anonymous Functions section of the manual which contains an example explaining the effect of quoting on byte compilation. – Constantine Nov 16 '14 at 0:08
  • @Constantine Done. I got lazy cause I'm on a phone, and the OP already linked it anyway. – Malabarba Nov 16 '14 at 0:09
  • Can you clarify what you mean about not using lexical binding and backtick? Thanks. – coredump Nov 16 '14 at 16:00
  • @coredump With dynamic binding, the only way to make outside variables accessible inside a lambda is to manually build the lambda as a list with the variable inside. Backtics are good for that kind of thing. – Malabarba Nov 16 '14 at 23:00
  • BTW, I don't think "once upon a time" really applies: when I investigated this subject in the revision history, I found that lambda has been defined as a macro which adds the function for as back as I could go. IOW if #' has been needed at some point, it was in very early development code. It sure was not needed already in Emacs-18. – Stefan Oct 13 '17 at 12:38
5

Since lambda doesn't make any sense when it's not quoted, recent versions of Emacs Lisp follow (ANSI) Common Lisp in interpreting unquoted (lambda...) as #'(lambda...). The two notations are almost exactly equivalent (except within quoted structure).

Whether to prefer (lambda...) or #'(lambda...) is therefore purely a matter of style. Some people prefer the naked form, which avoids syntactic noise, while others (including myself) prefer the quoted form.

  • This contradicts the elisp manual: "In Emacs Lisp, such a list is a valid expression which evaluates to a function object." – djechlin Mar 30 '15 at 3:51
  • 7
    "Recent versions" as in "versions released after 1990 or so" ;-) – Stefan Apr 27 '15 at 0:44
0

Adding a bit of additional history, on account of seeing Is #'(lambda ...) historical legacy?

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=4290 suggests that:

Starting with Emacs 22, a lambda form is byte-compiled when it is used as a function, regardless of whether it is preceded by function or #'. With Emacs versions prior to 22, you must explicitly use #' or function if you want the form to be byte-compiled.

I don't know about the byte-compiler, but I can see that at least as far back as 1993 the lambda macro itself returned a (function (lambda ...)) form.

https://www.iro.umontreal.ca/~monnier/hopl-4-emacs-lisp.pdf also says:

Interestingly (unlike MacLisp), lambda was not technically part of the Elisp language until around 1991 when it was added as a macro, early during the development of Emacs-19. In Emacs-18, anonymous functions were written as quoted values of the form:

'(lambda (..ARGS..) ..BODY..)

While the lambda macro has made this quote unnecessary for almost 30 years now, many instances of this practice still occur in Elisp code, even though it prevents byte-compilation of the body. Somewhat relatedly, only in 1993 did Lucid Emacs 19.8 import the #'... reader shorthand for (function ...) from MacLisp. Emacs followed suit the year after.

0

Just want to give an practical example of using backtic lambda expression. It's about lexical-binding / variable shadowing, using a backtic lambda expression and referencing variables with a comma makes it possible to get their global value.

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall `(lambda()
             (let ((my-variable "Random"))
               (message ,my-variable)))))

M-x [RET] eval-buffer outputs "Random old"

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall (lambda()
             (let ((my-variable "Random"))
               (message my-variable)))))

M-x [RET] eval-buffer outputs "Random"

A third example combining global variable and local variable of variable

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall `(lambda()
              (let ((my-variable "Random"))
                (message my-variable)
                (message ,my-variable)))))

M-x [RET] eval-buffer outputs "Random" "Random old"

  • @npostavs that was not the point with my example but I modified my example to avoid that bad practice as well – cjohansson Apr 18 at 13:29
  • Better, though I'm still not convinced this is an improvement over just choosing a different name for the inner binding. – npostavs Apr 18 at 15:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.