11

What is the difference between

(function (lambda ...))

and

(lambda ...) 

and

'(lambda ...)

?

It seems three are interchangeable in a lot of cases.

2 Answers 2

14

They are pretty interchangeable. The answer is that function enables the lambda to be byte compiled, whereas the other two do not (and are equivalent). Note: this does not mean that function actually byte compile the lambda.

How might one figure that out? A little Emacs lisp introspection provides some clues. To start: C-h f function RET:

function is a special form in 'C source code'.

(function arg)

Like 'quote', but preferred for objects which are functions. In byte compilation, 'function' causes its argument to be compiled. 'quote' cannot do that.

Ok, so that's the difference between (function (lambda ...)) and '(lambda ...), the first tells the byte compiler that it may safely compile the expression. Whereas the 'ed expressions may not necessarily be compiled (for they might just be a list of numbers.

What about just the bare (lambda ...)? C-h f lambda RET shows:

lambda is a Lisp macro in `subr.el'.

(lambda args [docstring] [interactive] body)

Return a lambda expression. 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, i.e., stored as the function value of a symbol, passed to 'funcall' or 'mapcar', etc.

Therefore, (lambda ...) and '(lambda ...) are equivalent.

Also, there is the notation #'(lambda ...), which is syntactic sugar for (function (lambda ...)).

For more information on functions in Emacs lisp, read the Functions info pages.

Just to check all this, you can type the following into the *scratch* buffer and evaluate the expressions:

(caddr '(lambda (x) (+ x x)))
(+ x x)

(caddr (lambda (x) (+ x x)))
(+ x x)

(caddr (function (lambda (x) (+ x x))))
(+ x x)

(equal '(lambda (x) (+ x x))
       (function (lambda (x) (+ x x))))
t

(equal '(lambda (x) (+ x x))
       (lambda (x) (+ x x)))
t

So, all three variants of using lambda just build up lists that may be used as functions (one of which may be byte compiled).

Sign up to request clarification or add additional context in comments.

6 Comments

But isn't using a single-quote in front of an expression making the LISP interpreter return it as-is and not evaluating it? That'd mean, that '(+ 1 2) will return as (+ 1 2) and (+ 1 2) will return as 3...
@Joscha, not sure what part you're commenting on. Lambda is self-quoting, which just means that when the interpreter evaluates a lambda expression, the result is that same lambda expression. I believe this is different than most other lisps because of the variable lookup used by Emacs (indefinite scope and dynamic extent). Scheme creates little closures with some environment information because of the lexical extent (I believe).
(lambda ...) is actually equivalent to (function (lambda ...)) not '(lambda ...) as you can try out by evaluating (macroexpand (lambda (x) (+ x x)))
@nschum And try (macroexpand '(lambda (x) (+ x x))) - same thing. I believe I've covered that in my answer (see the 2nd to last equal statement).
It seems like this answer has become partially wrong with age, and (lambda ...) is now equivalent to (function (lambda ...)) instead of (quote (lambda ...)).
|
4

Well (quote (lambda...)) and (lambda...) are not equivalent (when byte compiling). Quoted lambdas are not byte compiled whereas everything else is.

For example:

(defun foo (a)  
    (byte-code-function-p a))

(defun bar ()  
    (foo '(lambda () (ignore 'me))))

(defun bar2 ()  
   (foo (lambda () (ignore 'me))))

(defun bar3 ()  
    (foo (function (lambda () (ignore 'me)))))

(defun bar4 ()  
    (foo #'(lambda () (ignore 'me))))

(byte-compile 'bar)  
(byte-compile 'bar2)  
(byte-compile 'bar3)  
(byte-compile 'bar4)  

(bar)  ; -> nil  

(bar2) ; -> t  
(bar3) ; -> t  
(bar4) ; -> t

You usually don't want to quote a lambda unless the function you are going to pass the lambda to is doing something else with it than just funcall it.

1 Comment

I believe that this has changed over time. Looking at (info "(elisp)Anonymous Functions"), it says "Nowadays it is possible to omit 'function' entirely... This is because 'lambda' itself implies 'function'." That page is slightly confusing on first read, but your examples make for good clarification :) (a) (function (lambda ...)) is a variant of (quote (lambda ...)) which enables byte compilation. (b) un-quoted (lambda ...) is (nowadays) the same as (function (lambda ...)) !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.