年末年始から、An Introduction to Programming in Emacs Lispを読んでいます。
ちょっとつまずいた箇所があったので、まとめようと思います。
先にまとめ
Emacs 27.1でレキシカル・バインディングがデフォルトで有効になりました。
GNUのドキュメントでは、その点カバーできていない部分があるようなので、気をつけよう。
レキシカル・バインディングとダイナミック・バインディング
というか、レキシカルとかダイナミックとかって何?という話もあるので、簡単に。
(setq value 255)
(defun inner ()
(message "inner> value = %d" value))
(defun outer ()
(let ((value 0))
(message "outer> value = %d" value)
(inner)))
上記は、ダイナミック・バインディングが有効か、レキシカル・バインディングが有効かで動作が変わります。
ここでは、value
と名のついた変数が2つあります。
1つはsetq
で設定した、グローバル変数に相当するもの。値は255に束縛しています。
もう1つはlet
式内で定義された、outer
関数のローカル変数に相当するもの。値は0に束縛しています。
ダイナミックバインディングが有効な場合
上記のコードで、(outer)
を評価すると、ミニバッファは以下のように出力します:
outer> value = 0
inner> value = 0
inner> value = 0
とあるとおり、inner
関数はローカル変数のvalue
にアクセスしています。
outer
関数の中で呼び出されたinner
関数は、ダイナミック・バインディングにより、実行時に直近にある変数にアクセスしました。一番近くにあったのは、outer
内のローカル変数である value
。そのため、ミニバッファの出力は inner> value = 0
となりました。
レキシカル・バインディングが有効な場合
同様にして、ミニバッファは以下のように出力します:
outer> value = 0
inner> value = 255
inner> value = 0
ではなくなりました。レキシカル・バインディングにより、inner
関数がアクセスするのは、実行時ではなく、コード記述時点で直近にある変数 value
。つまり setq
で設定したグローバル変数の value
です。
Emacs 27.1からはレキシカル・バインディングがデフォルトで有効に
Emacs 27.1からはレキシカル・バインディングがデフォルトで有効になっています。
明示的にレキシカル・バインディングを有効にするには、(setq lexical-binding t)
とします。
lexical-binding ; => t
An Introduction to Programming in Emacs Lispでは、2023年1月現在、この変更に追従できていないのか、ダイナミック・バインディングがデフォルトと記述がされています (そこで混乱して、この文章をまとめるに至りました)。気をつけんとなぁ、と思います。
In computer science jargon, we would say the binding of a symbol is visible only in functions called in the let form; in Emacs Lisp, the default scoping is dynamic, not lexical. (The non-default lexical binding is not discussed in this manual.)
Prevent confusion (Programming in Emacs Lisp)