11

我现在正在学习参考手册中的 Emacs Lisp 和LISP Book 中的 Common Lisp 。

来自 Common Lisp 书

>> (setf power-of-two
     (let ((previous-power-of-two 1))
       #'(lambda ()
           (setf previous-power-of-two
             (* previous-power-of-two 2)))))

>> (funcall power-of-two)
2

>> (funcall power-of-two)
4

>> (funcall power-of-two)
8

由于它的动态绑定行为,该函数在 Emacs Lisp 中不起作用。

我想知道是否可以在不引入全局变量的情况下在 Emacs Lisp 中实现相同的功能?

4

4 回答 4

18

更新:

至此,Emacs 24 已经正式发布,lexical-let当缓冲区局部变量lexical-binding为非 nil 时,它支持不使用 的词法绑定。另请参阅M-: (info "(elisp) using lexical binding")和 pokita 的答案。


您可以lexical-letCommon Lisp Extensions(“CL 包”)中使用:

elisp> (require 'cl)
cl
elisp> (setf power-of-two
             (lexical-let ((previous-power-of-two 1))
               #'(lambda ()
                   (setf previous-power-of-two
                         (* previous-power-of-two 2)))))
(lambda
  (&rest --cl-rest--)
  (apply
   (lambda
     (G175638)
     (set G175638
          (*
           (symbol-value G175638)
           2)))
   '--previous-power-of-two-- --cl-rest--))

elisp> (funcall power-of-two)
2
elisp> (funcall power-of-two)
4
elisp> (funcall power-of-two)
8

我还听说过 GNU Emacs 的 lexbind 分支。

于 2011-08-05T11:47:21.240 回答
12

bzr 的 Emacs24 现在支持开箱即用的词法绑定;它只是在默认情况下没有被激活,因为有许多软件包仍然有意或无意地依赖于动态范围。您上面的代码应该在 Emacs24 中的变量“lexical-binding”设置为“t”的缓冲区中正常工作。

于 2011-08-05T12:03:51.627 回答
2

请参阅此页面:http ://www.emacswiki.org/emacs/FakeClosures

于 2011-09-10T17:46:52.153 回答
1

使用 Emacs 的 unintern 符号的另一种解决方案:

ELISP> (setf power-of-two
         (let ((p (make-symbol "previous-power-of-two")))
           (set p 1) (list 'lambda '()
           (list 'setf p
             (list '* p 2)))))

ELISP> (funcall power-of-two)
2
ELISP> (funcall power-of-two)
4
ELISP> (funcall power-of-two)
8
于 2011-12-12T12:30:50.727 回答