|
2.7.6 ブロックと局所値
モジュールを使うことで,変数の名前を局所的なものとして扱うことができる.場合によっては,変数の参照名は大域的なものとしておき,変数の取る値だけを局所化したい.これを行うには Blockを使う.

ブロックを使った局所値の設定
xを使った式を入力しておく.
In[1]:= x^2 + 3
Out[1]= 
入力した式を評価させる. xには局所的な値が使われる.
In[2]:= Block[{x = a + 1}, %]
Out[2]= 
xには何も大域的な値は割り当てられていない.
In[3]:= x
Out[3]= 
前節で説明したが, Module[ x , body]において,変数 xは常に固有な名前を参照するように設定される.つまり,モジュールが使われるたびに固有とされ,また,大域変数 xからも固有とされるように xは名前が変更される.これに対して,Block[ x , body]では, xは大域的なスコープを持つものとされる.ただし, xの取る値は局所的なものとされる.したがって,ブロックが終了すると, xには昔の値が戻される.ブロック内ではどんな値でも割り当てることができる.
シンボル tに値17を割り当てる.
In[4]:= t = 17
Out[4]= 
モジュール内の変数は固有の局所名を持つ.
In[5]:= Module[{t}, Print[t]]

ブロックでは,変数の大域名は維持されるが,変数の値は局所的なものでもよい.
In[6]:= Block[{t}, Print[t]]

ブロックにおいて,tには局所値が割り当てられる.
In[7]:= Block[{t}, t = 6; t^4 + 1]
Out[7]= 
ブロックの実行が終ると,もとの値が tに戻される.
In[8]:= t
Out[8]= 
ブロックを使うと,実効的に「局在化された環境」を作り出すことができる.この環境では変数の値を一時的に変更することができる.あるブロックの実行中に評価される式は,そのブロックにある変数に対して現時点で定義されている現行値を使う.同じことは,ブロックで直接記述される本体の各式だけでなく,各式の評価により生成される式についても言える.
シンボル uに対して遅延型の値を定義する.
In[9]:= u := x^2 + t^2
ブロックの外で uを評価させると, tに対する大域値が使われる.
In[10]:= u
Out[10]= 
tに対して,ブロック内での使用のための一時的な値を指定することもできる.
In[11]:= Block[{t = 5}, u + 7]
Out[11]= 
Do, Sum, Table等の反復処理を行う構成体ではブロックが使われる.これらの構成体では,実効的にブロックの機構が使われ反復変数がすべて局所的な値を持つものとして扱われている.
Sumを作用させると,自動的に反復変数 tの値が局所的なものにされる.
In[12]:= Sum[t^2, {t, 10}]
Out[12]= 
反復構成体における局所値化はブロックより多少だが一般化されている.つまり, a[1]や純粋な変数も局所値化の対象になる.
In[13]:= Sum[a[1]^2, {a[1], 10}]
Out[13]= 
直接引数としては与えられないが,関数の動作には影響を与える,という働きを持つ大域変数が使えると便利な場合がある.一例として,帰納的な反復回数の上限を決定するための大域変数 $RecursionLimitがある.この変数はすべての関数の評価に影響を及ぼすが,関数の直接の引数としては働かない.
大域変数に一度値が割り当てられると,特別に変更されるまでは,その値は変わらない.場合によっては,特定の計算だけとか計算の一部分だけで値を有効としたいときもある.それを行うにも,ブロックを使うことができる.
「大域変数」 tに依存する関数を定義 する.
In[14]:= f[x_] := x^2 + t
この場合, tの大域値が使われる.
In[15]:= f[a]
Out[15]= 
ブロックの中では tに対して局所値を設けることもできる.
In[16]:= Block[{t = 2}, f[b]]
Out[16]= 
大域変数を使い,関数のパラメータへの値の割当ての他に,関数からの結果の蓄積を行うこともできる.つまり,大域変数をあるブロックに対して局所化しておくことで,ブロックから呼び出される関数からだけの結果を蓄積させることができる.
この関数は,大域変数 tを増分し,その現行値を返す.
In[17]:= h[x_] := (t += x^2)
ブロックを使わないで h[a]を評価させると, tの大域値を変更する.
In[18]:= h[a]
Out[18]= 
ブロックを使うと, tの局所値だけが変わる.
In[19]:= Block[{t = 0}, h[c]]
Out[19]= 
tの大域値は同じままである.
In[20]:= t
Out[20]= 
Block[ x , body]等のブロックが評価されるときは, xに割り当てられている現行値が除去される.このため,理論上は,ブロックの中では xを実質的な「シンボル的な変数」として扱うことができる.しかし, xを戻り値としてブロックから返すと,それはブロック評価前の外部の値により置換されてしまう.
ブロックを評価させると, tの現行値は除去される.
In[21]:= Block[{t}, Print[Expand[(t + 1)^2]]]

tを含む式を戻り値とすると, tの大域値が使われ式の評価が行われる.
In[22]:= Block[{t}, t^2 - 3]
Out[22]= 
|