評価処理のトレース

Wolframシステムの標準評価処理は,ユーザの式の入力を取り込み,式を評価し,評価が完了したら結果を返す,という過程からなっている.本節では,最終的な評価結果だけでなく,中間過程でも評価がどう進行するのかを見ていく.そうすることで,評価処理の理解の助けにもなるだろう.

Trace[expr]expr の評価で生成されるすべての中間結果の式を列挙する
Trace[expr,form]パターン form にマッチする中間結果の式だけを列挙する

式評価のトレース

トレースさせると,式が計算され,直ちにが出力されてくる.
In[1]:=
Click for copyable input
Out[1]=
足し算の前にが評価されている.
In[2]:=
Click for copyable input
Out[2]=
ベキ項が評価されると,その結果はサブリストの形で出力される.
In[3]:=
Click for copyable input
Out[3]=

Trace[expr]を使えば,式 expr の評価過程において中間結果として生成されるすべての中間式を列挙させることができる.ただし,もとの式が簡単なものでないと,非常に長いリストが出力されてしまい,Traceを行っても何のことか分からなくなってしまう.

複雑な式をTraceする際は,もう1つの書式,Trace[expr,form]を使った方がよい.パターン form にマッチする中間式だけを選んで出力することができる.

階乗を計算するための帰納的関係を定義しておく.
In[4]:=
Click for copyable input
Out[4]=
階乗関数をトレースする.中間式をすべて出力したので,結果は非常に複雑なものになる.
In[5]:=
Click for copyable input
Out[5]=
次に,パターンを加えての形に準拠する中間式だけを出力する.
In[6]:=
Click for copyable input
Out[6]=
Traceで指定するパターンは何でもよい.例えば,これでもよい.
In[7]:=
Click for copyable input
Out[7]=

Trace[expr,form]を使うと,式 expr の評価過程で生成されるすべての中間式は一旦判定され,パターン form に合った式だけが抽出される.

例えば,関数を作ったとして,その関数が呼び出されているときだけトレースを実行したければ,パターンをにしTraceに与えておく.また,パターンをとしておけば,引数を伴った特殊構成の関数式だけを抽出できるようになる.

Wolframシステムによる典型的なプログラムでは,等の関数呼出しの式だけでなく,変数の割当てや,制御構造体等のいろいろな要素が登場する.これらの要素はすべて一般的な「式」とみなされるので,Traceに適切なパターン指定さえしておけば,どんな要素でも個別に抽出することができる.例えば,パターンをとしておけば,変数に関するどんな割当て式でも抽出できるようになる.

に関して生成される割当て式をすべて表示させる.
In[8]:=
Click for copyable input
Out[8]=

expr の評価において,そのどの過程で生成された中間式でもTrace[expr,form]を使えば限定抽出することができる.また,抽出すべき中間式は式 expr から直接得られるものでなくてもよい.つまり,expr の評価処理の一部として関数が呼び出され,その結果生成されるような式であってもよい.

トレースする関数を定義しておく.
In[9]:=
Click for copyable input
関数の評価中に生成される式を追跡する.
In[10]:=
Click for copyable input
Out[10]=

以上のように,Traceを使い中間式を追跡することができるが,追跡の対象になる式はユーザ定義の関数だけでなく,一部の組込み関数でもよい.ただし,注意点として組込み関数の場合,Wolframシステムのバージョンによってはアルゴリズムの記述や最適化処理が詳細な点で違うため,評価過程の順序が違ってくる場合がある.

Trace[expr,f[___]]式の評価における関数 f の呼出しをすべて表示する
Trace[expr,i=_]変数 i への割当て式だけを表示する
Trace[expr,_=_]すべての割当て式を表示する
Trace[expr,Message[___]]評価中に生成されるメッセージを表示する

Traceの限定

関数Traceにより出力される式のリストは,Wolframシステムの計算処理の履歴である.中間式は計算処理で実行された順序通りに並べられる.また,Traceの結果のリストは,ほとんどの場合,ネストされた形で出力されるが,これは実際に行われた計算の「構造」を表している.

基本的に,Traceの結果であるリストの持つサブリストは,特定のWolframシステム式の評価チェーン(鎖)を表す.また,サブリストの要素はチェーンに相当し,1つの式が取るいろいろな変換形を表している.ただし,通常は,1つの式を評価するには他の式も評価しなければならないので,実際のTraceでは,従属評価の結果もサブリストに含まれることになる.

割当ての列を定義する.
In[11]:=
Click for copyable input
Out[11]=
トレースすると,a[i]の変換処理の様子が評価チェーンとして現れる.
In[12]:=
Click for copyable input
Out[12]=
の簡約化処理で生成される式の形が評価チェーンの連鎖要素として表示される.
In[13]:=
Click for copyable input
Out[13]=
各関の各引数に数評価チェーンがあり,中間結果はサブリストの形で表示される.
In[14]:=
Click for copyable input
Out[14]=
評価チェーンは,式の要素別にサブリストで表示される.
In[15]:=
Click for copyable input
Out[15]=
ネストされた式をトレースすると,トレース結果のリストもネストされた形で返される.
In[16]:=
Click for copyable input
Out[16]=

あるWolframシステム式の評価において従属評価を必要とする状況は基本的に2つある.1つは,式が複数の副次的な式からなる場合で,そのとき各副次式は別々に評価される必要がある.もう1つは,式の評価において規則が適用され,その適用時に別の関連式をも評価する必要がある場合である.どちらの場合も,従属評価の結果は,Traceにより返される構造体におけるサブリストとして表される.

従属的評価は,の引数評価から派生する.
In[17]:=
Click for copyable input
Out[17]=
条件付き関数を定義する.
In[18]:=
Click for copyable input
の評価は,条件に関連した従属評価を伴う.
In[19]:=
Click for copyable input
Out[19]=

再帰的処理を踏む関数の評価をトレースさせると,結果はネストされたリスト形で得られる.これは,評価の対象となる関数は1つでも,反復過程の途中で新たに生成される中間式が評価前の中間式に従属する形で生成されるからである.

例えば,と定義を作り,を評価させたとすると,最初の評価ではが生成される.ここで,は従属評価から派生した式である.

が繰り返し評価され,中間結果がネストされたサブリストで表示される.
In[20]:=
Click for copyable input
Out[20]=
を直接fp[n]の値とする定義を作っておく.
In[21]:=
Click for copyable input
fp[n]の形の式は生成されることはないので,トレース結果にサブリストはない.
In[22]:=
Click for copyable input
Out[22]=
これは,Fibonacci数の再帰的定義である.
In[23]:=
Click for copyable input
最終条件を与える.
In[24]:=
Click for copyable input
Out[24]=
の再帰評価における全ステップが表示される.
In[25]:=
Click for copyable input
Out[25]=

式の評価過程で生成される中間式は,変換規則が適用された結果発生する.「異なるシンボルへの定義式の関連付け」で説明したように,定義済みの変換規則はすべて特定のシンボルに直接,もしくは,タグを介して間接的に関連付けられる.Trace[expr,f]を使い,式 expr をトレースさせることで,シンボル f に関連付けられている変換規則がどう適用されるかを調べることができる.この場合,Traceは,規則の適用前の中間式だけでなく,適用後の結果である中間式も返す.

Trace[expr,form]を使い式 expr をトレースさせると,パターン form にマッチした評価直前の中間式,または,そのパターンにマッチした,使われた規則に関連付けられたタグがすべて抽出される.

Trace[expr,f]式の評価において,f に関連した変換規則を使った評価ステップをすべて表示する
Trace[expr,f|g]f もしくは g に関連した評価ステップをすべて表示する

特定タグに関連した評価ステップのトレース

にマッチする中間式だけを表示させる.
In[26]:=
Click for copyable input
Out[26]=
シンボルに関連付けられている変換規則を使う評価ステップをすべて表示させる.
In[27]:=
Click for copyable input
Out[27]=
関数の規則を定義する.
In[28]:=
Click for copyable input
の評価過程をトレースさせ,に関連した変換規則をすべて表示させる.
In[29]:=
Click for copyable input
Out[29]=
Trace[expr,form,TraceOn->oform]中間式が oform にマッチした要素を持つときのステップだけをトレースする
Trace[expr,form,TraceOff->oform]中間式が oform にマッチした要素を持たないときのステップをトレースする

式の要素で範囲限定したトレース

Trace[expr,form]を使うと,パターン form に合った中間式だけが抽出されるが,トレース範囲としては,式 expr のすべての評価ステップが対象になる.場合によっては,expr の評価における範囲を限定して,限られたステップ中だけでトレースを行いたい.

これを行うには,TraceOn->oform のオプション設定を使う.パターン oform にマッチした要素を持つ中間式のステップに限ってトレースが実行される.反対に,あるステップだけをトレースから排除したければ,TraceOff->oform とすることで,oform を持つ中間式を除いたステップだけをトレースすることができる.

評価過程の全ステップをトレースする.
In[30]:=
Click for copyable input
Out[30]=
関連のステップだけをトレースする.
In[31]:=
Click for copyable input
Out[31]=
関連以外のステップをトレースする.
In[32]:=
Click for copyable input
Out[32]=
Trace[expr,lhs->rhs]expr の評価において,左辺 lhs にマッチするすべての中間式を抽出し,右辺 rhs に変換し表示する

評価中に生成される式への規則の適用

Traceが返すものをの評価で使われるの引数だけに限定する.
In[33]:=
Click for copyable input
Out[33]=

Trace関数の強力な面として,この関数により返されるリストは,基本的に,他の関数で操作できる標準的なWolframシステム式である.ただし,Traceによりリストの中の式にはHoldFormがかけられているので,そのままでは入力としては使うことができない.また,注意点として,HoldFormは内部で有効にはなっているが,表示が標準出力表記だと,HoldFormの記述自体は表示に現れない.

評価の全ステップをトレースさせる.
In[34]:=
Click for copyable input
Out[34]=
トレースされた中間式にはHoldFormがかけられているため,そのままでは入力には使えない.
標準の出力表記だと,どのリスト要素がTraceの評価結果のものか,または,評価前の式なのかは分かりづらい.
In[36]:=
Click for copyable input
Out[36]=
入力形で見るとはっきりする.
Traceで変換規則を使うと,規則の適用結果がまず評価され,それから,HoldFormが適用される.
In[38]:=
Click for copyable input
Out[38]=

複雑な計算では,Traceで得られるリストもまた複雑な構成になりがちである.Trace[expr,form]を使えば,パターン form に合った中間式だけをリストの要素として抽出することができる.しかし,どんなパターンを使おうが,最終的に得られるリストのネスト構造は変わらない.

をトレースさせ,のパターンに合った中間式を列挙させる.
In[39]:=
Click for copyable input
Out[39]=
今度は,だけを表示する.リストのネスト構成はのリストと同じであることに注目.
In[40]:=
Click for copyable input
Out[40]=

TraceDepth->n のオプション設定をTraceの指定に加えると,トレース可能なネストレベルの上限はレベル n に設定される.そうすることで,長くなる解法において,細かい計算をスキップし,主要ステップだけを追うことができるため,トレースの効率を上げることができる.さらに,オプションTraceDepthTraceOffを組み合せて使えば,追跡したいステップをさらに絞れるのでTrace作業をさらに速くすることができる.

ネストレベルが2以下のステップだけをトレースさせる.
In[41]:=
Click for copyable input
Out[41]=
Trace[expr,form,TraceDepth->n]expr のトレースにおいて,ネストレベル n 以下の評価ステップを列挙する

ネストレベルを限定したトレース

Trace[expr,form]を使えば,式 expr の評価で生成される中間式のうち form に合ったものだけを抽出することができる.ただし,この方法だと式だけが列挙され,式の評価から求まる値は通常出力されない.TraceForward->Trueのオプション指定をTraceに加えておけば,評価結果も見ることができる.

にマッチする中間式だけでなく,これらの式の評価結果も表示される.
In[42]:=
Click for copyable input
Out[42]=

Trace[expr,form]で抽出されるほとんどの式は評価チェーンの中間ステップで生成される式である.TraceForward->Trueの指定をした場合は,評価チェーンの最終ステップで得られる式もTrace結果に入れられる.また,指定をTraceForward->Allとすると,form にマッチした式が評価された後に評価チェーンにおいて生成されるすべての式が抽出される.

TraceForward->Allと指定したので,にマッチする式の後に生成される評価チェーンの全要素が抽出される.
In[43]:=
Click for copyable input
Out[43]=

TraceForwardを有効にしておくと,特定の形の式がどう評価されるかを追跡することができるようになる.場合によっては,式がこれからどうなるかより,どうしてこの式になったかを知りたい.そのときは,オプションTraceBackwardを有効にしておく.すると,TraceBackwardにより特定の式が生成される前に評価チェーンがどうだったかを観察することができるようになる.

をトレースする.の値はの評価によることが分かる.
In[44]:=
Click for copyable input
Out[44]=
の値に関連した評価チェーンの全容を追跡する.
In[45]:=
Click for copyable input
Out[45]=

TraceForwardTraceBackwardを使い分けると,評価チェーンを昇り降りして評価を追跡することができる.場合によっては,特定の評価チェーンから派生する子チェーンまで追跡したい.これを行うには,TraceAboveを指定する.例えば,TraceAbove->Trueと設定しておけば,関連するすべての子チェーンの最初と最後における中間式がTraceに含まれるようになる.また,TraceAbove->Allとしておけば,子チェーンの全ステップにおける式をTraceすることができるようになる.

子チェーンを含む全評価チェーンの最初と最後において,数を含む式を抽出させる.
In[46]:=
Click for copyable input
Out[46]=
をトレースする.を生成するチェーンにおける全ステップを抽出させる.
In[47]:=
Click for copyable input
Out[47]=
Trace[expr,form,opts]オプション設定に従って,式 expr の評価をトレースする
TraceForward->Trueform を含む評価チェーンの最後の式をリストに加える
TraceForward->All評価チェーンにおいて form 登場以降の全ステップで生成される式をリストに加える
TraceBackward->Trueform を含む評価チェーンにおいて最初の式をリストに加える
TraceBackward->All評価チェーンにおいて form 登場以前の全ステップで生成される式をリストに加える
TraceAbove->Trueform を含む子チェーンに通じる全評価チェーンにおいて最初と最後の式をリストに加える
TraceAbove->Allform を含む子チェーンに通じる全評価チェーンにおいて全ステップの式をリストに加える

トレースのリストに抽出されるステップを指定するためのオプション設定

Trace[expr,]の基本動作は次の通りである.まず,式 expr の評価の過程で生じる中間式が抽出される.次に,中間式がパターンや設定条件に見合うものかが判断され,そうならば,リスト出力用に内部保持される.このとき,式の持つ関数の引数が評価された後にできた中間式だけがTraceによる抽出の対象になる.また,TraceOriginal->Trueの設定が有効なら,引数が評価される前の式の形もTraceの対象にされる.

このトレースでは,引数評価の前と後で生成されるにマッチした式が抽出される.
In[48]:=
Click for copyable input
Out[48]=

Traceで得られるリストには,通常,非自明的な評価チェーンのステップで生成された式だけが出力される.つまり,評価後と評価前で同じ式が得られるような評価ステップは除外される.ただし,TraceOriginal->Trueの指定が有効なときはその限りでなく,Traceでは自明的かどうかにかかわらず評価過程の全ステップが出力される.

Traceが有効である場合,自明的な評価チェーンも含むすべての式がトレースさせる.
In[49]:=
Click for copyable input
Out[49]=
オプション
デフォルト値
TraceForwardFalseform 以降の評価チェーンの式を表示するかどうかを指定
TraceBackwardFalseform 以前の評価チェーンの式を表示するかどうかを指定
TraceAboveFalseform を含む子チェーンを生みだす評価チェーンを表示するかどうかを指定
TraceOriginalFalse頭部と引数の評価を実行する前の式を表示するかどうかを指定

Traceで使われる補足的なオプション

実行中のプログラムにTraceを使うとき,プログラム中の局所変数をどのように扱うか,という問題が起る.「モジュールの動作の仕方」で説明するように,Module等の構成体ではスコープを限定した局所変数が使えるようになっている.従って,プログラム中のもとのコードで変数を呼んでも,こうして設けられた局所変数には の形式で参照名が付けられる.

そこで,form に現れるシンボル x が,expr の実行で発生する形式 の名前を持つすべてのシンボルにデフォルトでマッチするように,Trace[expr,form]が設定される.つまり,Trace[expr,x=_]と入力すると,もとのプログラムにおいて変数が x の名前で参照されている限り,それが大域定義のものでも局所定義のものでもトレースの対象にされる.

Trace[expr,form,MatchLocalNames->False]
参照名が form で始まる局所変数をトレースリストから除外する

トレースからの局所変数の除外

場合によっては,名前を x とする大域変数だけをトレースの対象としたい.局所変数の記述名がxであってもそれは除外したい.そうするには,MatchLocalNames->Falseのオプション設定を加えておく.

形式の名前を持つ変数すべてに関連した割当て評価をトレースする.
In[50]:=
Click for copyable input
Out[50]=
今度は,大域変数 x に限ってトレースする.
In[51]:=
Click for copyable input
Out[51]=

関数Traceを使うと,まず,式の計算処理が完全に実行され,次に,計算処理の履歴を示す中間式のリストが表示される.特に,計算が長くなる場合は,計算処理の進行に並行した形で随時トレース結果を観測することができると便利である.関数TracePrintを使えばそれが可能になる.この関数は機能上Traceと同じだが,表示の仕方が違う.つまり,Traceのように抽出したすべての式を最後にリストで一括表示するのではなく,中間式が生成されるたびに式の表示を逐一行う.

の評価で生成される式を生成時に逐一表示させる.
In[52]:=
Click for copyable input
Out[52]=

TracePrintにより返される一連の式は,Traceが返すリスト要素の式と同じである.TracePrintの式の表示において,画面左側のインデント幅は式のネストレベルを示している(これは,Traceリストにおけるサブリストのレベルに相当する).TracePrintの動作設定には,Traceの設定で使ったオプションTraceOnTraceOffTraceForwardを使うことができる.ただし,TracePrintは順次,式を出力していくので,TraceBackwardの指定は行うことができない.また,TraceOriginalの設定値は実効的に常にTrueとされる.

Trace[expr,]expr の評価をトレースし,抽出した中間式は評価終了時にリスト形式で一括表示する
TracePrint[expr,]expr の評価をトレースし,抽出した中間式は評価中に逐次表示する
TraceDialog[expr,]expr の評価をトレースし,指定した中間式が生成されるとダイアログを開始する
TraceScan[f,expr,]expr の評価をトレースし,HoldForm適用の中間式に f を適用する

評価処理をトレースするための関数

の評価で,が生成されるとダイアログモードが開始する.
In[53]:=
Click for copyable input
Out[53]=
ダイアログが始まると,スタックを参照し,現在位置を確認する.
In[54]:=
Click for copyable input
(Dialog) Out[54]=
ダイアログを終了する.戻り値としての最終評価結果が得られる.
In[55]:=
Click for copyable input
Out[55]=

TraceDialogを使うと,計算処理を途中で一旦停止させ,停止時の演算環境をもとにWolframシステムと対話ができるようになる.評価で一時的に使われる変数の現行値を調べたり,別の値に再設定したりすることができる.ただし,微妙な点で(特に,パターンやモジュール変数等に関連した点で),通常の割当てとは違うので注意が必要である.

TraceDialogのトレース中に一連の式が生成されると関数Dialogが呼び出される(Dialogの機能詳細に関しては「ダイアログ」を参照のこと).Dialogを呼び出すということは,2次的な計算セッションを開始させるということで,Wolframシステムとの対話は別の入出力行が使われ進行する.

expr のトレースで抽出される中間式に任意な関数 f を適用したければ,TraceScan[f,expr,]の書式を使う.実際に f の適用がある式にはHoldFormが適用され,評価されないよう式が保護される.

TraceScan[f,expr,]では,中間式が評価される前に関数 f が適用される.ここで,TraceScan[f,expr,patt,fp]を使うと,評価の前には f が適用され,評価の後には fp が適用されるようになる.