概要
Mathematicaの標準関数Tableは例えば
In := Table[i^2,{i,1,5}]
Out = {1,4,9,16,25}
のように, ダミー変数iを含んだ形で書かれる.
ダミー変数を使うことで変数が局所化され, iの定義に関係なく式が評価されるようになる.
この記事では, このようなダミー変数を含む自作の関数の作り方について解説する.
実装
問題
次のような挙動をする関数を実装できれば十分だろう.
In := val[f[t],t,a]
Out = f[a]
ここでvalの各引数は
- 第1引数: ダミー変数を含む関数
- 第2引数: ダミー変数の指定
- 第3引数: ダミー変数の値の指定
を表している.
解答
この実装にはBlockとSetAttributesを用いて次のようにする.
In := SetAttributes[val, HoldAll]
val[f_,t_,a_]:=Block[{t=a},f]
1行目は関数valに対してHoldAll属性を与えている.
このHoldAll属性はvalの全ての引数の評価を事前に行わない事を意味している.
http://reference.wolfram.com/language/ref/HoldAll.html
これでダミー変数が事前に定義されていたとしても問題なく動作するようになる.
2行目のBlockは変数tを局所的なものとして扱うためである.
http://reference.wolfram.com/language/ref/Block.html
要するにこれだけである.
以下ではもう少し補足的説明を与える.
誤答例
この実装までに幾つかの試行錯誤があった
Blockの代わりにReplaceAll, Function, Module, Withを使えば次のように書ける.
In := SetAttributes[val1, HoldAll]
val1[f_,t_,a_]:=f/.t->a
SetAttributes[val2, HoldAll]
val2[f_,t_,a_]:=Function[t,f][a]
SetAttributes[val3, HoldAll]
val3[f_,t_,a_]:=Module[{t=a},f]
SetAttributes[val4, HoldAll]
val4[f_,t_,a_]:=With[{t=a},f]
ReplaceAll以外の関数はtが事前に定義されていたとしても問題なく評価される.
In := t=1;
{val[s^2,s,2], val[t^2,t,2]} (*Block*)
{val1[s^2,s,2], val1[t^2,t,2]} (*ReplaceAll*)
{val2[s^2,s,2], val2[t^2,t,2]} (*Function*)
{val3[s^2,s,2], val3[t^2,t,2]} (*Module*)
{val4[s^2,s,2], val4[t^2,t,2]} (*With*)
Out = {4,4}
{4,2}
{4,4}
{4,4}
{4,4}
ReplaceAllでの結果が{4,1}とならずに{4,2}となっているのは, 1$(=1^2)$が2に置換されたためである.
ではFunction, Module, Withを用いた実装がBlockと同じかと言えば, そうではない.
次の例を見る.
In := u=v^2
val[u,v,2] (*Block*)
val1[u,v,2] (*ReplaceAll*)
val2[u,v,2] (*Function*)
val3[u,v,2] (*Module*)
val4[u,v,2] (*With*)
Out = 4
4
v^2
v^2
v^2
関数がダミー変数を含んだ遅延評価で定義される場合では, このような違いが生まれるのである.
標準関数Tableも次のようにBlockの場合と同じ挙動を示す.
In := j=i^2;
Table[j,{i,1,5}]
Out = {1,4,9,16,25}
これらの挙動の違いはHULINKS blogの次の記事が分かりやすいかも知れない:
http://blog.hulinks.co.jp/2011/06/with-module-and-block-in-mathematica.html
よもやま話
標準関数でのダミー変数
Mathematicaでダミー変数を扱う標準関数はTableの他にもPlotがある.
しかし一見ダミー変数を扱っているように見えても, 実際には扱っていない関数も存在する.
次に幾つかの例を示そう.
ダミー変数を使うもの (変数が局所化される)
TablePlotNDIntegrate
ダミー変数を使わないもの (変数が局所化されない)
DIntegrateSolve
Dにおいてダミー変数が使われていないのは, 次のような評価を想定しているためかも知れない.
In := D[2 Sin[x], Sin[x]]
Out = 2
(しかしこのような使い方は挙動が安心できないので避けるべきではある..)
(NIntegrateとIntegrateとで挙動が違うのは些か恐ろしく感じる)
ダミー変数の呼び方
便宜的に「ダミー変数」と書いたが, これはMathematicaでの正式な用語ではないようである.
http://reference.wolfram.com/language/ref/Table.html にはTableの変数の扱いについて次のような記述があり, 「ダミー変数」とは書かれていない.
Tableは,Blockを使って実質的には値や変数を局所化する.
Mathematicaのシンタックスハイライタのオプションにはダミー変数について次のようにも書かれている.
日本語: 引数に使うことで特別な意味を持つ変数
英語: Valiables made special by use in arguments
シンタックスハイライタ
Mathematicaのnotebook上ではこれはlocal scope conflict(構文警告)としてシンタックスハイライトされるが, 問題なく評価される. (次画像の赤字)
前述のTable, Plotなどの標準関数ではダミー変数のシンタックスハイライトが機能するが, ここで扱った自前関数のダミー変数はシンタックスハイライトされていない.
Mathematicaにはそのようなカスタマイズ機能は無いように見えたが, もしご存知の方が居ればコメントして頂けると幸いである.
ダウンロード
本記事の内容を含んだnbファイルは以下からダウンロード出来る.
https://www.dropbox.com/s/w6xotj3bli9kmeu/DummyVariables.nb?dl=0
他参考資料
標準評価手順 (Wolfram ドキュメントセンター):
https://reference.wolfram.com/language/tutorial/TheStandardEvaluationProcedure.html
数学のダミー変数 (Wolfram ドキュメントセンター):
http://reference.wolfram.com/language/tutorial/DummyVariablesInMathematics.html.ja



