|
2.6.6 パターン,規則,定義の評価
式の評価とパターンマッチングの処理では,いくつかの相互作用的な操作が必要になる.第一に,パターンマッチングでは,検索の対象となる式は少なくとも部分的に評価済みである.このため,パターン自体もあらかじめ評価しておいた方が都合がよい.
この例では,あらかじめパターンが評価される.このため,パターンは与えられた式にマッチする.
In[1]:= f[k^2] /. f[x_^(1 + 1)] -> p[x]
Out[1]= 
/;条件の右辺は,パターンマッチングに使われるまで未評価のままにされる.
In[2]:= f[{a, b}] /. f[list_ /; Length[list] > 1] -> list^2
Out[2]= 
場合によっては,パターンの全部もしくは一部を評価不可としておきたい.そうするには,HoldPatternを評価不可にしたい部分に作用させる.つまり,評価したくないパターンがpattならば,HoldPattern[patt]と記述する.すると,パターンとしてのpattの機能はそのまま保持されるが,パターン自体は未評価のままおかれる.

パターン評価の保留
HoldPatternの応用ケースとして,まだ評価されていない式や未評価の形におかれた式に対して適用するためのパターンの指定がある.
HoldPatternを作用させたため,1 + 1は評価不可になり,演算子/.の左辺にある1 + 1にマッチするようになる.
In[3]:= Hold[u[1 + 1]] /. HoldPattern[1 + 1] -> x
Out[3]= 
注意してほしいのは,ホールドHoldのような関数を使うと式の評価を保留にすることができることである.しかし,このような関数は,/.や他の演算子を伴った式において,式の部分に対する操作には影響しない.
これは,rが引数を原子オブジェクトとしないときにその値を定義する.
In[4]:= r[x_] := x^2 /; !AtomQ[x]
条件に合わないので関数の定義は適用されない.
In[5]:= r[3]
Out[5]= 
しかし,パターンx_は,rの定義に従って変換される.
In[6]:= r[x_]
Out[6]= 
HoldPatternを作用させr[x_]を評価不可の形に変換しておかないと,先の定義が適用されてしまう.
In[7]:= {r[3], r[5]} /. HoldPattern[r[x_]] -> x
Out[7]= 
上の例で示したように,通常,lhs -> rhsのような変換規則において左辺lhsはすぐに評価されてしまう.規則は,普通,すでに評価済みの式に対して適用されるからである.また,lhs -> rhsにおける右辺rhsはすぐに評価される.ただし,遅延型の規則lhs :> rhsを使えば,右辺rhsは評価しないまま保持しておくことができる.
->による規則は直ちに評価されるが,:>の規則は評価されない.
In[8]:= {{x -> 1 + 1}, {x :> 1 + 1}}
Out[8]= 
両方の規則を適用したらどうなるか見てみよう.:>規則の右辺は,未評価のままHold式に組み込まれる.
In[9]:= {x^2, Hold[x]} /. %
Out[9]= 

変換規則における評価
変換規則の左辺は普通評価されるが,定義の左辺は普通評価されない.理由は次のとおりである.変換規則は,通常,/.を介して評価済みの式に適用される.これに対して,定義は評価の過程で適用される.つまり,まだ完全に評価の済んでいない式に適用される.定義をこのような式に対して適用可とするには,定義の左辺を少なくとも一部未評価のまま保持しておく必要がある.
最も単純なケースとして,シンボルに対する定義がある.前節で説明したが,x = valueの定義において,左辺にあるシンボルxは評価されないまま残される.もしも,定義が与えられる前に,xにyが割り当てられ,その上で,x = valueにより左辺が評価されることになったなら,y = valueといったおかしな定義が発生してしまう.
定義を作る.左辺のシンボルは評価されない.
In[10]:= k = w[3]
Out[10]= 
シンボルを定義しなおす.
In[11]:= k = w[4]
Out[11]= 
左辺を強制的に評価する.すると,シンボルkではなく,シンボルの値であるw[4]が定義される.
In[12]:= Evaluate[k] = w[5]
Out[12]= 
w[4]の値はw[5]になっている.
In[13]:= w[4]
Out[13]= 
定義の左辺にある個々のシンボルは評価されないが,左辺が複雑な式からなるときは,それらが部分的に評価されることもある.例えば,左辺がf[args]のような形を取るとき,引数部argsは前もって評価される.
1 + 1はあらかじめ評価される.このため,値はg[2]に対して定義される.
In[14]:= g[1 + 1] = 5
Out[14]= 
gに定義された値を確認する.
In[15]:= ?g


定義の左辺に現れる関数において,その引数部を先に評価しなければならない理由は,ある式の評価においてこの定義がどう使われるかを考えるとよく分かる.2.6.1で説明したように,関数が評価されるときは,関数の持つ引数がまず評価の対象になる.その次に,関数に関連した定義が検索され,見付かればそれが適用される.つまり,定義を関数に適用する前に,引数はすでに評価済みでなければならない.ただし,例外が1つある.それは,対象となる関数が特別な属性を備えており,引数の評価が保留になっているときである.

定義における評価
定義の左辺に現れる関数において,その引数が先に評価されることは,普通,適切である.しかし,状況によっては,そうしたくない場合もある.そのようなときは,評価不可としたい部分に対してHoldPatternを作用させておく.
|