GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/eintr/Lexical-vs-Dynamic-Binding-Example.html ・ emacs-doc.conao3.com

レキシカル束縛と動的束縛の例

場合によっては、レキシカル束縛と動的束縛のどちらも同じように動作します。しかし、場合によっては、プログラムの意味が変わってしまうことがあります。例えば、レキシカル束縛の下でこのコードで何が起こるか見てみましょう:

;;; -*- lexical-binding: t -*-

(setq x 0)

(defun getx ()
  x)

(setq x 1)

(let ((x 2))
  (getx))
     ⇒ 1

ここでは、(getx) の結果は 1 となります。字句束縛の下では、getx は let 式の値を参照しません。これは、getx の本体が let 式の本体の外側にあるためです。getx はコードのグローバルレベル(つまり、いかなる let 式の本体内でもない場所)で定義されているため、グローバルレベルでも x を探し、見つけ出します。getx を実行する際、x の現在のグローバル値は 1 であるため、getx はその結果を返します。

代わりに動的バインディングを使用すると、挙動が異なります:

;;; -*- lexical-binding: t -*-

(defvar x) ;; Use dynamic binding for 'x'.

(setq x 0)

(defun getx ()
  x)

(setq x 1)

(let ((x 2))
  (getx))
     ⇒ 2

さて、(getx) の結果は 2 になります!これは、動的バインディングにおいて、getx を実行する際、スタックの最上部にある x の現在のバインディングが、let のバインディングによるものだからです。今回、getx は x のグローバル値を参照しません。というのも、そのバインディングが、バインディングスタックにおける let 式のバインディングよりも下にあるためです。

(上記の defvar 宣言により、変数が「特殊」なものとなり、デフォルトのバインディング規則ではなく動的バインディング規則に従うようになります。defvar による変数の初期化 を参照してください。)