2013 年 5 月の更新: GNU Emacs 24.3.1 の時点で、(let .. (defun..)) は警告なしで問題なくバイトコンパイルされ、バイトコンパイルされたコードはコンパイルされていないコードと同じように機能します。バイトコンパイルするファイルにfile 変数を追加することを忘れないでくださいlexical-binding: t
。この質問の最後にある回避策は不要になりました。
レキシカル バインディング - Emacs Lisp マニュアルには次の段落があります。
symbol-value、boundp、set などの関数は、変数の動的バインディング (つまり、そのシンボルの値セルの内容) のみを取得または変更することに注意してください。また、defun または defmacro の本体のコードは、周囲のレキシカル変数を参照できません。
2 番目の文の意味を正しく理解しているかどうかはわかりません。レキシカル バインディング モードで実行する必要がある次のコードでは、defun の本体のコードが name のレキシカル バインディング値を正常に参照していますn
。
(let ((n 0))
(defun my-counter ()
(incf n)))
(my-counter) ;; 1
(my-counter) ;; 2
(let .. (defun ..)) は悪い習慣だと言っているだけですか?
回避策:
;; -*- lexical-binding: t -*-
;; a way to define the counter function without byte-compile error or warning
(defvar my--counter-func
(let ((n 0))
(lambda ()
(setq n (1+ n)))))
(defun my-counter ()
(funcall my--counter-func))
;; another way to define the counter function, again without byte-compile error or warning
(fset 'my-another-counter
(let ((n 0))
(lambda ()
(setq n (1+ n)))))
上記のコードをテストするためのコードは次のとおりです。
;; run:
;; emacs -q --load path-to-the-el-file-of-this-code.el
(load "path-to-file-defining-my-counter.elc") ;; loading the ELC file to test if byte-compiled code runs as expected.
(print (my-counter)) ;; 1
(print (my-counter)) ;; 2
(print (my-another-counter)) ;; 1
(print (my-another-counter)) ;; 2