Next: , Previous: , Up: Variables   [Contents][Index]


11.3 ローカル変数

グローバル変数は新しい値で明示的に置き換えるまで値が持続します。変数にローカル値(local value) — Lispプログラム内の特定の部分で効果をもつ — を与えると便利なときがあります。変数がローカル値をもつとき、わたしたちは変数がその値にローカルにバインド(locally bound)されていると言い、その変数をローカル変数(local variable)と呼びます。

たとえば関数が呼び出されるとき、関数の引数となる変数はローカル値(その関数の呼び出しにおいて実際の引数に与えられた値)を受け取ります。これらのローカルバインディングは、その関数のbody内で効果をもちます。他にもたとえばスペシャルフォームletは特定の変数にたいして明示的にローカルなバインディングを確立し、これはletフォームのbody内で効果を持ちます。

これにたいしてグローバルなバインディング(global binding)とは、(概念的には)グローバルな値が保持される場所です。

ローカルバインディングを確立すると、その変数の以前の値は他の場所に保存されます(または失われる)。わたしたちはこれを、以前の値がシャドー(shadowed)されたと言います。シャドーはグローバル変数とローカル変数の両方で発生し得ます。ローカルバインディングが効果を持つときには、ローカル変数にsetqを使用することにより、指定した値をローカルバインディングに格納します。ローカルバインディングが効果を持たなくなったとき、以前にシャドーされた値が復元されます(または失われる)。

変数は同時に複数のローカルバインディングを持つことができます(たとえばその変数をバインドするネストされたlet)。カレントバインディング(current binding)とは、実際に効果を持つローカルバインディングのことです。カレントバインディングは、その変数の評価によりリターンされる値を決定し、setqにより影響を受けるバインディングです。

ほとんどの用途において、最内(innermost)のローカルバインディングとローカルバインディングをもたないグローバルバインディングを、カレントバインディングと考えることができます。より正確に言うと、スコープルール(scoping rule)と呼ばれるルールは、プログラム内でローカルバインディングが効果を持つ任意の与えられた場所を決定します。Emacs Lispのスコープルールはダイナミックスコープ(dynamic scoping)と呼ばれ、これは単に実行中のプログラム内の与えられた位置でのカレントバインディングを示しており、その変数がまだ存在すれば、その変数にたいしてもっとも最近作成されたバインディングです。ダイナミックスコープについての詳細、およびその代替であるレキシカルスコープ(lexical scoping)と呼ばれるスコープルールについては、Variable Scopingを参照してください。

スペシャルフォームletlet*は、ローカルバインディングを作成するために存在します:

Special Form: let (bindings…) forms…

このスペシャルフォームは、bindingsにより指定される特定の変数セットにたいするローカルバインディングをセットアップしてから、formsのすべてをテキスト順に評価する。これはforms内の最後のフォームの値をリターンする。

bindingsの各バインディングは2つの形式のいずれかである。(i) シンボルなら、そのシンボルはnilにローカルにバインドされる。(ii) フォーム(symbol value-form)のリストなら、symbolvalue-formを評価した結果へローカルにバインドされる。value-formが省略されたらnilが使用される。

bindings内のすべてのvalue-formは、シンボルがそれらにバインドされるに、記述された順番に評価される。以下の例ではzyの新しい値(つまり1)にではなく、古い値(つまり2)にバインドされる。

(setq y 2)
     ⇒ 2

(let ((y 1)
      (z y))
  (list y z))
     ⇒ (1 2)

その一方でbindingsの順序は指定されない。以下の例では1か2のどちらかがプリントされる。

(let ((x 1)
      (x 2))
  (print x))

したがって単一のletフォーム内で変数を複数回バインディングするのは避けること。

Special Form: let* (bindings…) forms…

このスペシャルフォームはletと似ているが、次の変数値にたいするローカル値を計算する前に、ローカル値を計算してそれを変数にバインドする。したがてbindings内の式は、このlet*フォーム内の前のシンボルのバインドを参照できる。以下の例を上記letの例と比較されたい。

(setq y 2)
     ⇒ 2

(let* ((y 1)
       (z y))    ; yの値に今計算されたばかりの値を使用する
  (list y z))
     ⇒ (1 1)

以下はローカルバインディングを作成する他の機能のリストです:

変数はバッファーローカルなバインディングを持つこともできます(Buffer-Local Variablesを参照)。数は多くありませんが、端末ローカル(terminal-local)なバインディングをもつ変数もあります(Multiple Terminalsを参照)。この種のバインディングは、通常のローカルバインディングのように機能することもありますが、これらはEmacs内のどこにいるかに依存してローカルになります。

User Option: max-specpdl-size

この変数はローカルな変数バインディングと、unwind-protectにゆるクリーンアップ(Cleaning Up from Nonlocal Exitsを参照)の総数にたいする制限を定義し、この変数を越えるとEmacsは(データ"Variable binding depth exceeds max-specpdl-size"とともに)エラーをシグナルする。

このリミットは、もし超過したときにエラーが関連付けられていれば、誤って定義された関数による無限再起を避けるための1つの手段になる。ネストの深さにたいする他の制限としては、max-lisp-eval-depthがある。Evalを参照のこと。

デフォルト値は1300。Lispデバッガーのエントリーしたとき、もし残りが少なければ、デバッガーを実行するための空きを作るために値が増加される。