次: , 前: Extent, 上: Variable Scoping


10.9.3 動的スコープの実装

(Emacs Lispの実際の動作とは異なるが)単純な実装例が、 動的束縛を理解する助けになるでしょう。 この技法を深い束縛(ディープバインディング、deep binding)と呼び、 初期のLispシステムで使われていました。

変数・値の対である束縛のスタックがあるとしましょう。 関数やフォームletに入ると、 引数やローカル変数の束縛をスタックに積みます。 束縛を作った構造から抜けるとそれらの束縛を取りさります。

変数の値は、スタックの先頭から底へ向けてその変数の束縛を探索します。 その束縛から得る値が変数の値になります。 変数に設定するには、現在の束縛を探して、その束縛に新たな値を格納します。

これからわかるように、関数の束縛は、その関数の実行中には、 たとえ別の関数を呼び出していても、存続しています。 これが束縛の存続が動的であるという理由です。 また、その束縛が有効である期間中ならば、同じ変数を使えば他の関数からも 束縛を参照できるのです。 これがスコープが無限であるという理由です。

GNU Emacs Lispにおいて、変数のスコープの実際の実装には、 浅い束縛(シャローバインディング、shallow binding)と呼ばれる 技法を用いています。 各変数には現在値を保存しておく標準の場所、シンボルの値セルがあります。

浅い束縛では、変数の設定は値セルに値を格納することで動作します。 新たな束縛を作成すると(以前の束縛に属する)古い値をスタックに積み、 新たなローカル値を値セルに格納します。 束縛を解くときには、古い値をスタックから取り出して値セルに格納します。

浅い束縛を用いる理由は、束縛を探索する必要がないため、 深い束縛と同じ結果を持ちながら高速に動作するからです。