Search code examples
variablesemacslexical-scope

Elisp extend variable lifetime


I have a loop in which I create a local variable during each iteration. I then declare a lambda that uses the local variable sometime in the future.

      (dolist (entry (read-lines "~/.emacs-projects"))
         (let ((project (car (json-read-from-string entry)))) ;; <---- I NEED THIS ONE
             (widget-create 'link
                     :button-prefix ""
                     :button-suffix ""
                     :action (lambda (wid &rest ignore) (load-project project)) ;; HERE
                     (format "%s : %s\n" (car project) (cdr project)))))

In the code above I create project and when :action triggers I want to use project as an argument to another function. Currently i am getting Symbol’s value as variable is void: project when the lambda is run which makes me think that the outer scope is not preserved.

How can I extend the lifetime of project so that I can access it in the lambda?


Solution

  • You want to use the lexically scoped flavor of Emacs Lisp, which was one of the main novelties added to Emacs-24. To do it, just add the following somewhere (usually inside a comment) on the first line of your Elisp file:

    -*- lexical-binding:t -*-
    

    Hopefully, at some point in the future, the old dynamically-scoped dialect will not be the default any more.