emacslispevalquotebackquote

format of lambda in emacs lisp


I'm tring to apply closure in emacs lisp.And I find a post here: How do I do closures in Emacs Lisp?

with some code like:

(defun foo (x) `(lambda () ,x)) (message (string (funcall (foo 66))))

But following the emacs documentation lambda should be formated like '(lambda () x) ==> using this format ,I got an ERROR :Symbol's value as variable is void: x

When " , " is add betwenn "()" and "x" ,everything goes right .

Why?


Solution

  • This happens because Emacs Lisp is dynamically scoped thus foo returns a lambda where x is free. That's what the error tells you.

    To do a closure in Emacs Lisp you have to use lexical-let which simulates a lexical binding and therefore allows you to make a real closure.

    (defun foo (x)
      (lexical-let ((x x))
                   (lambda () x)))
    
    (message (string (funcall (foo 66))))
    

    Here are some links from the Emacs Wiki:

    1. Dynamic Binding Vs Lexical Binding
    2. Fake Closures

    Note that you could have defined x with a let like this:

    (defun foo (x)
      (lambda () x))
    
    (message (string (let ((x 66)) (funcall 
                                    (foo 'i-dont-care)))))