如何克服 emacs lisp 闭包缺少局部变量的问题

发布于 2024-11-28 05:32:10 字数 630 浏览 2 评论 0原文

我现在正在学习 参考手册 中的 Emacs Lisp 和来自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 中实现相同的功能而不引入全局变量?

I'm now studying Emacs Lisp from the reference manual and Common Lisp from a LISP Book.

from the Common Lisp book

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

The function won't work in Emacs Lisp because of its dynamic binding behavior.

I wonder if it is possible to implement the same function in Emacs Lisp without introducing a global variable ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

萤火眠眠 2024-12-05 05:32:11

另一个使用 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

another solution using Emacs' unintern symbol:

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
陌生 2024-12-05 05:32:10

更新:

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


您可以使用 Common Lisp 中的 lexical-let扩展(“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 分支。

Update:

By now, Emacs 24 has been officially released, and it supports lexical binding without using lexical-let, when the buffer-local variable lexical-binding is non-nil. See also M-: (info "(elisp) using lexical binding") and pokita's answer.


You can use lexical-let from the Common Lisp Extensions (the "CL package"):

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

I've also heard about a lexbind branch of GNU Emacs.

窗影残 2024-12-05 05:32:10

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

Emacs24 from bzr now supports lexical binding out of the box; it just isn't activated by default since there are many packages which still deliberately or inadvertently depend on dynamical scoping. Your above code should work just fine in Emacs24 in a buffer where the variable 'lexical-binding' is set to 't'.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文