Elisp продлевает время жизни переменной - PullRequest
1 голос
/ 16 февраля 2020

У меня есть al oop, в котором я создаю локальную переменную во время каждой итерации. Затем я объявляю лямбду, которая когда-нибудь в будущем использует локальную переменную.

      (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)))))

В приведенном выше коде я создаю project, а когда срабатывает :action, я хочу использовать project в качестве аргумента для другая функция. В настоящее время я получаю Symbol’s value as variable is void: project, когда запускается лямбда, что заставляет меня думать, что внешняя область не сохраняется.

Как я могу продлить время жизни project, чтобы я мог получить к нему доступ в лямбде?

Ответы [ 2 ]

2 голосов
/ 17 февраля 2020

Вы хотите использовать лексически ограниченную версию Emacs Lisp, которая была одной из главных новинок, добавленных в Emacs-24. Чтобы сделать это, просто добавьте следующее (обычно внутри комментария) в первую строку вашего файла Elisp:

-*- lexical-binding:t -*-

Надеемся, что в какой-то момент в будущем старый диалект с динамической областью не будет быть больше по умолчанию.

2 голосов
/ 17 февраля 2020

Либо используйте лексическую область видимости (не nil переменная lexical-binding), либо используйте лямбда-форму списка со значением project, заменяющим саму переменную:

 (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)))))

Если вашей функции действия на самом деле не нужна project в качестве переменной , а просто нужно ее значение, тогда вы можете просто подставить значение, как показано.

Но в этом case ваша лямбда-форма будет списком (чья машина lambda, et c.), поэтому она не будет распознана как функция до ее оценки. В частности, байтовый компилятор будет видеть его только как список, а не как функцию.

...