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

12.10.2 動的束縛

現代のLisp方言では、特殊変数(後述)および旧Lisp方言のすべての変数において、ローカル変数の束縛は動的です。(Lisp方言の選択を参照してください。)動的な変数束縛には用途もありますが、一般的に字句的な束縛よりもエラーが発生しやすく効率も劣り、コンパイラが動的束縛を用いたコードの誤りを検出する能力も低くなります。

変数が動的にバインドされている場合、Lispプログラムの実行中の任意の時点におけるその変数の現在のバインドは、単にそのシンボルに対して直近に作成された動的ローカルバインドであり、そのようなローカルバインドが存在しない場合はグローバルバインドとなる。

動的束縛は、以下の例に示すように、動的なスコープと範囲を持ちます。

(defvar x -99)  ; x receives an initial value of −99.

(defun getx ()
  x)            ; x is used free in this function.

(let ((x 1))    ; x is dynamically bound.
  (getx))
     ⇒ 1

;; After the let form finishes, x reverts to its
;; previous value, which is −99.

(getx)
     ⇒ -99

関数 getx は x を参照します。これは、その defun 構文自体の中に x の束縛が存在しないという意味で、フリーな参照です。x が(動的に)束縛されている let フォーム内から getx を呼び出すと、ローカル値(すなわち 1)が取得されます。一方、let フォームの外から getx を呼び出すと、グローバル値(すなわち −99)が取得されます。

以下に、setq を用いて動的に束縛された変数を設定する例をもう一つ示します。

(defvar x -99)      ; x receives an initial value of −99.

(defun addx ()
  (setq x (1+ x)))  ; Add 1 to x and return its new value.

(let ((x 1))
  (addx)
  (addx))
     ⇒ 3           ; The two addx calls add to x twice.

;; After the let form finishes, x reverts to its
;; previous value, which is −99.

(addx)
     ⇒ -98

字句束縛が有効であっても、特定の変数は引き続き動的に束縛されます。これらは特殊変数と呼ばれます。defvar、defcustom、またはdefconstで定義されたすべての変数は特殊変数です(グローバル変数の定義を参照)。それ以外のすべての変数は字句束縛の対象となります。

値を指定せずに defvar を使用することで、他の箇所では字句的にバインドしつつ、特定のファイル内、あるいはファイルの一部だけで変数を動的にバインドすることが可能です。例えば:

(let (_)
  (defvar x)      ; Let-bindings of x will be dynamic within this let.
  (let ((x -99))  ; This is a dynamic binding of x.
    (defun get-dynamic-x ()
      x)))

(let ((x 'lexical)) ; This is a lexical binding of x.
  (defun get-lexical-x ()
    x))

(let (_)
  (defvar x)
  (let ((x 'dynamic))
    (list (get-lexical-x)
          (get-dynamic-x))))
    ⇒ (lexical dynamic)
関数: special-variable-p symbol

この関数は、symbol が特殊変数(すなわち、defvar、defcustom、または defconst の変数定義を持つ)である場合に non-nil を返します。それ以外の場合、戻り値は nil となります。

なお、これは関数であるため、恒久的に特殊な変数に対してのみ non-nil を返すことができ、現在の字句スコープ内でのみ特殊な変数に対しては返せない点に注意してください。

関数の仮引数として特殊変数を使用することはサポートされていません。

動的束縛は、Emacs Lispにおいてシンプルな方法で実装されています。各シンボルには値セルがあり、そこで現在の動的値(あるいは値がないこと)が指定されます。シンボルの構成要素を参照してください。シンボルに動的なローカル束縛が与えられると、Emacsは値セルの内容(あるいはその内容がないこと)をスタックに記録し、新しいローカル値を値セルに格納します。束縛構文の実行が完了すると、Emacsはスタックから古い値をポップし、それを値セルに格納します。