Mathematicaプログラミング

■ 関数

シンボルに値や式などを割り当てることで関数を表現する。

関数定義

関数は以下のようして定義を行う。

In[1]:= foo[x_] := x+1

In[2]:= foo[10]

Out[2]= 11

In[1]で関数fooを定義し、In[2]で実際に使用を行っている。

関数の中身を複数行にわたって書きたいときは以下のように括弧を使用する。

In[1]:= hoo[x_, y_] := (
          z=x+y;
          z+1
        )

In[2]:= hoo[5, 10]

Out[2]= 16

式の区切り目には「;」を使用し、最後に評価された式が関数の戻り値となる。

ここで、最後の式には「;」を付けないように注意すること。

使用してしまうと戻り値は「Null」となってしまう。

In[1]:= hoo[x_, y_] := (
          z=x+y;
          z+1;
        )

In[2]:= hoo[3, 4] // FullForm

Out[2]//FullForm= Null

最後の行にセミコロンを使用したい場合は「Return」を使用する。

In[1]:= hoo[x_, y_] := (
          z=x+y;
          Return[z+1];
        )

In[2]:= hoo[2, 5]

Out[2]= 8

むろん、「Return」を使用すれば関数の途中で脱出することも可能となる。

引数のパターンマッチ

関数の仮引数の部分はパターンマッチとなっている。

「foo[x_]」の「x_」はあらゆる1つの式にマッチし、 その式にxという名前を付けるという意味となる。

「foo[x]」とするとシンボルxにのみマッチする関数となる。

同じ名前の関数は任意個定義することができ、呼び出し時には一番適合する関数が適用される。

定義;

foo[a]        := 1   (* 引数がaの時のみ適用される *)
foo[b]        := 2   (* 引数がbの時のみ適用される *)
foo[_]        := 3   (* 任意の1引数に適用される *)
foo[_Integer] := 4   (* 引数が整数の時のみ適用される *)
foo[_, _]     := 5   (* 任意の2引数に適用される *)
foo[d, _]     := 6   (* 第一引数がdで、第2引数が任意の式の時に適用される *)
foo[__]       := 7   (* 任意の1個以上の引数に適用される *)
foo[___]      := 8   (* 任意の0個以上の引数に適用される *)
foo[a, ___]   := 9   (* 第一引数がaで、第2引数以降0個以上の任意の式の時に適用される *)
実行結果:

foo[a]
1

foo[2]
4

foo[x]
3

foo[1.5]
3

foo[1, 2]
5

foo[d, 5]
6

foo[1,3,4]
7

foo[]
8

foo[a, 2]
5

foo[a, 2, 2]
9

ローカル変数(シンボル)

「Module」、「Block」、「With」を使用する事で、 局所的な変数、関数(広く言えばシンボル)を定義することができる。

定義は以下のようになる。

Module[{ローカルシンボル}, 式]
Block[{ローカルシンボル}, 式]
With[{ローカルシンボル}, 式]

「With」を用いると宣言されたシンボルは定数となる。

「With」の方が「Module」や「Block」よりも速いので値を書き換える必要がない場合は できる限り「With」を使用した方が良い。

「Module」と「Block」の挙動は細かいところを見ると相当違いがあるが、 「Block」はクセが強いので特別な理由がない限り「Module」を使用した方がよい。

また、ローカルシンボルは宣言時に初期化可能である。

ソース:

num = 10
Print["#", num]
hoo[a_] := Module[{num=a, xyz},
  Print["%", num];
  num=50;
  xyz=333;
  Print["@", num]
]
hoo[30]
Print["&", num]
実行結果:

#10
%30
@50
&10

Moduleの挙動

Moduleを使用するとローカルシンボルを使用することができるが、 実際には特別な名前を使用したグローバルな変数を定義しているだけである。

ソース:

Print[FullForm[xyz]]
Print[$ModuleNumber]

bar[] := Module[{xyz},
  Print[FullForm[xyz]];
  Print[$ModuleNumber];
]

bar[]
bar[]
実行結果:

xyz
15
xyz$15
16
xyz$16
17

この様に変数xyzを定義した場合「xyz$整数」という名前の変数が作成され、 整数の部分は$ModuleNumberという変数の値が使用される。

$ModuleNumberの値はModuleを使用する旅にインクリメントされる。

純関数(無名関数)

「&」の利用

以下のように「&」を使用することで純関数を定義することが可能である。

In[1]:= execBy5[func_] := func[5]

In[2]:= execBy5[(#*10)&]

Out[2]= 50

「(#*10)&」によって、引数を一つ取りそれを10倍する関数の定義を行っている。

複数の引数を取りたいときは以下のようにする。

In[1]:= execBy5and6[func_] := func[5, 6]

In[2]:= execBy5and6[(#1+#2)&]

Out[2]= 11

「#1」が第一引数、「#2」が第二引数となる。

むろん、この調子で#3, #4, ....とすれば任意個の引数に対応可能である。

なお、先ほどの例のように「#」と「#1」は同じ意味となる。

「Function」の利用

先ほどは「&」を使用したが、「Function」を使用しても同じことができる。

In[1]:= execBy5and6[func_] := func[5, 6]

In[2]:= execBy5and6[Function[{x,y}, x*y]]

Out[2]= 30

純関数のなかで純関数を使用したいときなどは、 こちらを使用した方が便利かもしれない。

引数には値を代入することはできない

以下のように、引数はパターンのため値を代入することはできない。

foo[x_] := (
  x=x+1; (* xは変数ではないので代入不可能 *)
  x*10
)