ダミー変数を含む関数の実装 [Mathematica]

# 概要
Mathematicaの標準関数`Table`は例えば

```mathematica:
In := Table[i^2,{i,1,5}]
Out = {1,4,9,16,25}
```

のように, ダミー変数`i`を含んだ形で書かれる.
ダミー変数を使うことで変数が局所化され, `i`の定義に関係なく式が評価されるようになる.
この記事では, このようなダミー変数を含む自作の関数の作り方について解説する.

# 実装
## 問題
次のような挙動をする関数を実装できれば十分だろう.

```mathematica:
In := val[f[t],t,a]
Out = f[a]
```

ここで`val`の各引数は

* 第1引数: ダミー変数を含む関数
* 第2引数: ダミー変数の指定
* 第3引数: ダミー変数の値の指定

を表している.

## 解答
この実装には`Block`と`SetAttributes`を用いて次のようにする.

```mathematica:
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`を使えば次のように書ける.

```mathematica:
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`が事前に定義されていたとしても問題なく評価される.

```mathematica:
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`と同じかと言えば, そうではない.
次の例を見る.

```mathematica:
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`の場合と同じ挙動を示す.

```mathematica:
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`がある.
しかし一見ダミー変数を扱っているように見えても, 実際には扱っていない関数も存在する.
次に幾つかの例を示そう.

ダミー変数を使うもの (変数が局所化される)

* `Table`
* `Plot`
* `NDIntegrate`

![](https://i.imgur.com/UZtz3h6.png)


ダミー変数を使わないもの (変数が局所化されない)

* `D`
* `Integrate`
* `Solve`

![](https://i.imgur.com/gYzMXOa.png)

`D`においてダミー変数が使われていないのは, 次のような評価を想定しているためかも知れない.

```mathematica:
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(構文警告)としてシンタックスハイライトされるが, 問題なく評価される. (次画像の赤字)

![](https://i.imgur.com/Jld0hTK.png)

前述の`Table`, `Plot`などの標準関数ではダミー変数のシンタックスハイライトが機能するが, ここで扱った自前関数のダミー変数はシンタックスハイライトされていない.

![](https://i.imgur.com/XjpJmto.png)

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