Next: , Previous: , Up: 変数のバインディングのスコーピングルール   [Contents][Index]


12.10.2 ダイナミックバインディング

Local variable bindings are dynamic in the modern Lisp dialect for special variables (see below), and for all variables in the old Lisp dialect. (See Selecting Lisp Dialect.) Dynamic variable bindings have their uses but are in general more error-prone and less efficient than lexical bindings, and the compiler is less able to find mistakes in code using dynamic bindings.

When a variable is dynamically bound, its current binding at any point in the execution of the Lisp program is simply the most recently-created dynamic local binding for that symbol, or the global binding if there is no such local binding.

以下の例のように、ダイナミックバインディングはダイナミックスコープとダイナミックエクステントをもちます:

(defvar x -99)  ; xは初期値として-99を受け取る

(defun getx ()
  x)            ; この関数内ではxは自由に使用される

(let ((x 1))    ; xはダイナミックにバインドされている
  (getx))
     ⇒ 1

;; letフォームが終了した後に
;; xは前の値-99にリバートされる

(getx)
     ⇒ -99

関数getxxを参照します。defun構文自体の中にxにたいするバインディングが存在しないという意味において、これはフリーな参照です。xが(ダイナミックに)バインドされているletフォーム内からgetxを呼び出すと、ローカル値(つまり1)が取得されます。しかしその後letフォームの外側からgetxを呼び出すと、グローバル値(つまり-99)が取得されます。

以下はsetqを使用してダイナミックに変数をバインドする例です:

(defvar x -99)      ; xは初期値として-99を受け取る

(defun addx ()
  (setq x (1+ x)))  ; xに1加算して新しい値をリターンする

(let ((x 1))
  (addx)
  (addx))
     ⇒ 3           ; addxを2回呼び出すとxに2回加算される

;; letフォームが終了した後に
;; xは前の値-99にリバートされる

(addx)
     ⇒ -98

レキシカルバインディングが有効な場合でも、特定の変数はダイナミックにバインドされたままです。これらはスペシャル変数(special variable)と呼ばれます。defvardefcustomdefconstで定義されたすべての変数はスペシャル変数です(グローバル変数の定義を参照)。その他のすべての変数はレキシカルバインディングの対象になります。

値なしでdefvarを使用することにより、他の場所ではレキシカルにバインドされている状態のまま、単一ファイルやファイルの一部だけで変数をダイナミックにバインドすることが可能になります。たとえば:

(let (_)
  (defvar x)      ; xへのletバインドはこのlet内ではダイナミック
  (let ((x -99))  ; これはxのダイナミックバインド
    (defun get-dynamic-x ()
      x)))

(let ((x 'lexical)) ; これはxのレキシカルバインド
  (defun get-lexical-x ()
    x))

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

この関数はsymbolがスペシャル変数(つまり変数がdefvardefcustomdefconstによる定義をもつ)なら非nilをリターンする。、それ以外ならリターン値はnil

これは関数なので永続的にスペシャルな変数には非nilをリターンできるが、カレントレキシカルスコープでのみスペシャルな変数では異なることに注意。

関数内の正式な引数としてのスペシャル変数の使用はサポートされていません。

Emacs Lispでのダイナミックバインディングは、シンプルな方法で実装されています。シンボルはそれぞれ、シンボルのカレントのダイナミック値(または値の不在)を指定する値セルをもちます。シンボルの構成要素を参照してください。あるシンボルがダイナミックなローカル値を与えられたとき、Emacsは値セルの内容(または値の不在)をスタックに記録して、新しいローカル値を値セルに格納します。バインディング構文が実行を終えたとき、Emacsはスタックから古い値をpopして値セルにそれを配置します。

This page has generated for branch:master, commit:762705fb24fd90db318f2e51c1e762452d26f7e2 to check Japanese translation.