プログラミング言語理論では、非ローカル変数はローカルスコープで定義されていない変数です。この用語はグローバル変数を指すこともありますが、主にネストされた関数や匿名関数のコンテキストで使用され、一部の変数はローカルスコープにもグローバル スコープにも属さない場合があります。
Luaではこれらは関数の上位値と呼ばれます。 [1]
例
ネストされた関数
inner次の Python 3 の例では、別の関数 のスコープ内にネストされた関数が定義されていますouter。変数はxに対してローカルですouterが、 に対しては非ローカルですinner(グローバルでもありません)。
def outer ():
x = 1
def inner ():
nonlocal x
x += 1
print ( x )
return inner
Javascript では、変数の局所性は、varこの変数に最も近いステートメントによって決定されます。次の例では、 にはステートメントが含まれているため は に対してx局所的ですが、 にはステートメントが含まれていないため、 x は に対して非局所的です。
outer var xinnerinner
関数外側() { var x = 1 ;関数内側( ) { x += 1 ; console.log ( x ) ; }戻り内側; }
匿名関数
次の Haskell の例では、変数はc匿名関数内で非ローカルです\x -> x + c。
外側=としますc = 1 in map ( \ x -> x + c ) [ 1 , 2 , 3 , 4 , 5 ]
実装上の問題
非ローカル変数は、プログラミング言語で ネストされた、匿名の、高階の、したがってファーストクラスの関数をサポートすることが難しい主な理由です。
ネストされた関数が(相互に)再帰的である場合、フレーム ポインターはネストされた関数自体のローカル変数のみを指し、その間のスタックには任意の数のアクティベーション レコードが存在する可能性があるため、コンパイラーがコール スタックのどこに非ローカル変数が割り当てられたかを正確に把握することが難しくなります。これは通常、アクセス リンクまたはディスプレイ レジスタを使用して解決されます。
ネストされた関数が高階関数の引数として渡される場合、非ローカル変数を見つけるためにクロージャを構築する必要があります。ネストされた関数が外部関数の結果として返される (または変数に格納される) 場合、非ローカル変数はスタック上で使用できなくなります。代わりにヒープに割り当てる必要があり、その有効期間は、それらを宣言して割り当てた外部関数の有効期間を超えて延長されます。通常、これにはガベージ コレクションが必要です。
注記
- ^ プログラミング言語 Lua (初版)、「27.3.3 – 上位値」
参考文献
- Aho、Lam、Sethi、Ullman。「7.3 スタック上の非ローカル データへのアクセス」。コンパイラ: 原理、テクニック、ツール。第 2 版。
