Peter Seibel の「Practical Common Lisp」という本を読んでいます。
第6章の「変数」セクションの「レキシカル変数とクロージャー」と「動的変数、別名特殊変数」。 http://www.gigamonkeys.com/book/variables.html
私の問題は、両方のセクションの例が (let ...) がどのようにグローバル変数をシャドウできるかを示しており、実際には動的変数とレキシカル変数の違いを教えていないことです。
クロージャーがどのように機能するかは理解していますが、この例の let の何が特別なのかはわかりません。
(defvar *x* 10)
(defun foo ()
(format t "Before assignment~18tX: ~d~%" *x*)
(setf *x* (+ 1 *x*))
(format t "After assignment~18tX: ~d~%" *x*))
(defun bar ()
(foo)
(let ((*x* 20)) (foo))
(foo))
CL-USER> (foo)
Before assignment X: 10
After assignment X: 11
NIL
CL-USER> (bar)
Before assignment X: 11
After assignment X: 12
Before assignment X: 20
After assignment X: 21
Before assignment X: 12
After assignment X: 13
NIL
ここでは特に何も起こっていないように感じます。barの外側のfooはグローバルxをインクリメントし、 letのbarで囲まれたfooはシャドウされたxをインクリメントします。大したことは何ですか?これが字句変数と動的変数の違いをどのように説明するのかわかりません。しかし、この本は次のように続けています。
では、これはどのように機能するのでしょうか。LET は、 xをバインドするときに、通常の字句バインディングではなく動的バインディングを作成することになっていることをどのように認識しますか? 名前が特別に宣言されているため、それは認識されます.12 DEFVAR および DEFPARAMETER で定義されたすべての変数の名前は、自動的にグローバルに特別に宣言されます。
「通常の字句結合」を使用してletがxを結合するとどうなるでしょうか? 全体として、動的バインディングと字句バインディングの違いは何ですか? また、動的バインディングに関してこの例はどのように特別なのでしょうか?