|
2.6.12 発展:評価処理用スタック
Mathematica内部には「評価スタック」と呼ばれる現在評価中の式を記録しておく場所が用意されている.関数Stackを使うと,そのスタックの記録内容を参照できる.計算を一時停止させたとき等にStackを実行し計算の状態がどうなっているか調べることができる.
評価スタックにおける式は,最も最近評価された式がスタックの最後の式となるように並べられる.すでに評価が進行している式は,スタックの先頭寄りにおかれる.
例えば,式f [g[x]]の評価において,現時点でxが評価されているとする.スタックを参照すると f [g[x]], g[x], x の順序で評価が進んでいる旨が表示される.
Stack[_]は,それが呼び出されるときに評価中の式を返す.その中にはPrint関数も含まれる.
In[1]:= f[g[ Print[Stack[_]] ]] ;

Stack[ ]は,呼び出されるときに進行中の評価に関連したタグを返す.
In[2]:= f[g[ Print[Stack[ ]] ]] ;

評価スタックは,特定の計算においてMathematicaの現在位置に到達するまでに,どの関数がどの他の関数を呼び出したかを表示してくれるものととらえることができる.こうして表示される式の列は,オプションTraceAboveをTrueとしたときのTrace関数により返される一連のネストしたリストの第1要素に相当する.

評価スタックの参照
通常の入出力セッションで直接Stackを使うことはあまりないだろう.通常は,計算を一時保留にしてからダイアログモードにまず入り,その後で2次的セッションからStackを実行する(ダイアログに関しては2.14.2を参照のこと).
階乗のための標準的な帰納的関数を定義しておく.
In[3]:= fac[1] = 1; fac[n_] := n fac[n-1]
fac[10]の評価をトレースし,fac[4]が現れた時点でダイアログモードに入る.
In[4]:= TraceDialog[fac[10], fac[4]]

Out[5]= 
ダイアログが開始したので,まず,スタックを調べ,どんなオブジェクトが評価中かを見てみる.
In[5]:= Stack[ ]
Out[6]= 
ダイアログを終了する.
In[6]:= Return[ ]

Out[4]= 
最も単純なのは,評価スタックが評価中のすべての式を記録できるように設定されている場合である.しかし,場合によっては,網羅しない方がよいときもある.例えば,Print[Stack[ ]]が実行されると,Printが常にスタックの最後の関数になってしまうため不具合が生じる.
StackInhibitを使えば,そのようなことが起らないようにできる.書式StackInhibit[expr]を使うと,式exprの評価はされるが,評価で発生する関数呼出しはスタックに登録されないようになる.
StackInhibitを使いPrintがスタックに記録されないようにしておく.
In[7]:= f[g[ StackInhibit[Print[Stack[ ]]] ]] ;
Out[5]= 
TraceDialog等の関数を使いダイアログを開始させると,StackInhibitはその都度自動的に呼び出される.このため,ダイアログの中で使われた関数はStackでは表示されない.

評価スタックの制御
StackInhibitとStackBeginを使い評価プロセスのどの部分をスタックに記録するか指定できる.StackBegin[expr]は,式exprが評価される前に新たなスタックを用意する.つまり,スタックには式exprの評価で使われたもの以外は記録されない.StackBeginの前に使われた関数等は入らない.TraceDialog[expr, ... ]等のダイアログ用関数では,まずStackBeginが呼び出され,それから式exprが評価される.このため,スタックを参照することで,式exprがどのように評価されるかは知ることができるが,TraceDialog自体がどう呼ばれたかは分からない.
StackBegin[expr]は,exprの評価に新たなスタックを使う.
In[8]:= f[ StackBegin[ g[h[ StackInhibit[Print[Stack[ ]]] ]] ] ]

Out[6]= 
Stackは現在評価中の式だけを表示する.このため,最も最近の式の形が表示される.しかし,場合によっては,過去に取った式の形を見ることができると好都合である.これを行うには,StackCompleteを使う.
StackComplete[expr]を使うと,評価中の各式から派生した評価チェーンの逐一をスタックに記録することができる.この機能は,TraceにTraceAbove -> TrueとTraceBackward -> Allのオプション設定をしたときに得られる機能に相当する.
|