11

私は今、Emacs Lisp をリファレンス マニュアルから、Common Lisp をLISP Book から勉強しています。

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

アップデート:

lexical-let現在、Emacs 24 が公式にリリースされており、バッファーローカル変数lexical-bindingが非 nilの場合、を使用せずにレキシカルバインディングをサポートしています。またM-: (info "(elisp) using lexical binding")、ポキタの答えも参照してください。


Common Lisp Extensions (「CL パッケージ」)lexical-letから使用できます。

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 は、すぐにレキシカルバインディングをサポートするようになりました。意図的または不注意に動的スコープに依存している多くのパッケージがあるため、デフォルトではアクティブ化されていません。上記のコードは、変数 'lexical-binding' が 't' に設定されているバッファー内の Emacs24 で問題なく動作するはずです。

于 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 に答える