vava
vava

Reputation: 25381

How do I do closures in Emacs Lisp?

I'm trying to create a function on the fly that would return one constant value.

In JavaScript and other modern imperative languages I would use closures:

function id(a) {
    return function() {return a;};
}

but Emacs lisp doesn't support those.

I can create mix of identity function and partial function application but it's not supported either.

So how do I do that?

Upvotes: 32

Views: 7793

Answers (7)

Felipe
Felipe

Reputation: 17181

;; -*- lexical-binding:t -*-

(defun create-counter ()
  (let ((c 0))
    (lambda ()
      (setq c (+ c 1))
      c)))

(setq counter (create-counter))

(funcall counter) ; => 1
(funcall counter) ; => 2
(funcall counter) ; => 3 ...

Upvotes: 4

Bernard Hurley
Bernard Hurley

Reputation: 366

Real (Not Fake) Closures in Emacs 24.

Although Emacs 24 has lexical scooping when the variable lexical-binding has value t, the defun special form doesn’t work properly in lexically bound contexts (at least not in Emacs 24.2.1.) This makes it difficult, but not impossible, to define real (not fake) closures. For example:

(let ((counter 0))
   (defun counting ()
    (setq counter (1+ counter))))

will not work as expected because the symbol counter in the defun will be bound to the global variable of that name, if there is one, and not the lexical variable define in the let. When the function counting is called, if the global variable doesn’t, exist then it will obviously fail. Hoever if there is such a global variable it be updated, which is probably not what was intended and could be a hard to trace bug since the function might appear to be working properly.

The byte compiler does give a warning if you use defun in this way and presumably the issue will be addressed in some future version of Emacs, but until then the following macro can be used:

(defmacro defun** (name args &rest body)
  "Define NAME as a function in a lexically bound context.

Like normal `defun', except that it works correctly in lexically
bound contexts.

\(fn NAME ARGLIST [DOCSTRING] BODY...)"
  (let ((bound-as-var (boundp  `,name)))
    (when (fboundp `,name)
      (message "Redefining function/macro: %s" `,name))
    (append
     `(progn
        (defvar ,name nil)
        (fset (quote ,name) (lambda (,@args) ,@body)))
     (if bound-as-var
         'nil
         `((makunbound `,name))))))

If you define counting as follows:

(let ((counter 0))
  (defun** counting ()
    (setq counter (1+ counter))))

it will work as expected and update the lexically bound variable count every time it is invoked, while returning the new value.

CAVEAT: The macro will not work properly if you try to defun** a function with the same name as one of the lexically bound variables. I.e if you do something like:

(let ((dont-do-this 10))
  (defun** dont-do-this ()
    .........
    .........))

I can’t imagine anyone actually doing that but it was worth a mention.

Note: I have named the macro defun** so that it doesn’t clash with the macro defun* in the cl package, however it doesn’t depend in any way on that package.

Upvotes: 13

Steve Yu
Steve Yu

Reputation: 49

Emacs 24 has lexical binding.

http://www.emacswiki.org/emacs/LexicalBinding

Upvotes: 4

Allen
Allen

Reputation: 5110

Emacs lisp only has dynamic scoping. There's a lexical-let macro that approximates lexical scoping through a rather terrible hack.

Upvotes: 7

vava
vava

Reputation: 25381

Found another solution with lexical-let

(defun foo (n) 
    (lexical-let ((n n)) #'(lambda() n)))

(funcall (foo 10)) ;; => 10

Upvotes: 35

Ken
Ken

Reputation: 5224

Stupid idea: how about:

(defun foo (x)
  `(lambda () ,x))

(funcall (foo 10))  ;; => 10

Upvotes: 10

Related Questions