私はEmacsの字句スコープ(Emacs 24の新機能)間の相互作用を実験してadd-to-list
いて、相互作用が混乱していることに気づき、それを理解する方法がわかりません。set
の代わりに使用することを除いて、これは最小限の例ですadd-to-list
。(通常、引用符で囲まれた変数名を使用するという点でset
似ています)add-to-list
(eval
'(progn
(setq a "global")
(let ((a "apple"))
(defun my-print-a ()
(print a)
(set 'a "by set")
(print a))
(setq a "mature apple"))
(let ((a "banana"))
(my-print-a))
(print a))
t) ;; t for lexical scoping
上記のコードは、「mature apple」、「mature apple」、「byset」を順番に出力します。最初の印刷結果である「成熟したリンゴ」は、字句スコープ(字句クロージャをサポート)で期待どおりであり、ここで驚くことはありません。しかし、2番目と3番目の印刷の結果は私には驚くべきものです。これ(set 'a "by set")
は、名前のグローバルバインディングを認識して影響を与えるだけであるかのようですa
。
これは意図された動作ですか?それともこれはバグですか?意図されている場合、この動作をどのように理解しますか?
set
字句スコープがオンになっている限り、影響を与えるのは常にグローバルバインディングであると想定するのは正しいですか?
を使用(eval '(progn ...) nil)
すると、動的スコープで期待どおりに動作し、の動作はその場合(set 'a ...)
と同じになり(setq a ...)
ます。字句スコープと引用符で囲まれた変数を一緒に使用する場合にのみ、この落とし穴が表示されます。
アップデート:
マニュアルによると、意図した動作のようです。ボイド変数については、マニュアルによると
字句バインディングルールでは、値セルは変数のグローバル値、つまり字句バインディング構造の外側の値のみを保持します。変数が字句的にバインドされている場合、ローカル値は字句環境によって決定されます。シンボルの値セルが割り当てられていない場合、変数はローカル値を持つ可能性があります。
symbol-value、boundp、setなどの関数は、変数の動的バインディング(つまり、シンボルの値セルの内容)のみを取得または変更します。
symbol-value、boundp、setは、通常、引用符で囲まれた変数名((symbol-value 'var) (boundp 'var) (set 'var 123)
)で呼び出される関数です。これらの関数は、シンボルの値セルのみを取得または設定し、字句バインディングルールでは、値セルはグローバル値のみを保持します。したがって、字句バインディングでは、引用符で囲まれた変数を使用すると、グローバル値のみが取得または設定されます(変数が特別な変数でない場合)。結果が字句(リンゴ)でも動的(バナナ)でもないという点でまだ奇妙に思えますが。