Mathematica はプログラミング言語なので、 Mathematica で何かをするというのは、何らかのプログラムを書くということだ。僕がこの Mathematica 言語をなんとなく使えるようになっていちばん驚いたのが、いわゆる「言語の予約語」で実現されている構造が、極端に少ないらしいことだ。言語の予約語とは、例えば比較文を作るための if とか、繰り返しを実現するための for とか、そういう「言語の基本機能提供のために、他に使うことができない単語」のこと。

極端に言えば、Mathematica プログラムのすべてのコードは、それらの文の構造も含めて、内部的には次のたった1つの形態およびその組み合わせとして実現されている。

頭部[引数1, 引数2, 引数3...]

例えば、変数 a に b + 3.2 を代入する次の文を見てみる。

a = b + 3.2

これは、 Mathematica 内部では次の形に等価なものとして扱われている。

Set[a, Plus[b, 3.2]]

つまり、代入のための演算子 = は Set 関数の省略表記にすぎないということだ。同じように、足し算の演算子 + も Plus 関数の省略表記だ。

代入を実現する関数 Set は、つまり「第1引数で与えられるシンボルに、第2引数の内容を評価したものを割り当てた上で、その評価結果を返す」という動作を実装していると理解することができる。この説明は、 = による単純な代入を回りくどく言い換えているにすぎないが、こう理解しておくと、 Mathematica 学習話(?)で最初の難関となっている、即時定義と遅延定義もすっきり理解できる。遅延定義は、関数の定義でよく使う := を使った代入文のこと。この := は SetDelayed 関数と等価で、「第1引数で与えられるシンボルに、未評価でそのままの形の第2引数を割り当てる」という内容なのだ。具体的には、

f[x_] := x^2

は、

SetDelayed[f[x : Blank[]], Power[x, 2]]

と等価なのである(パターンの説明はここではおく)。つまり、 Set(=)と SetDelayed(:=) の違いは、これらの評価のタイミングで第2引数を評価するかどうかの違いなのだ。置き換え規則の定義である -> (Rule):> (RuleDelayed)についてもまったく同様。

セミコロンによる出力の抑制も、同じ原理の省略表記である。例えば、

x = 3;
y = 5;
z = x + y

とやると、z の値である 8 だけが出力セルに表示されるが、これは、

CompoundExpression[Set[x, 3], Set[y, 5], Set[z, Plus[x, y]]]

と等しい。 CompoundExpression は、「引数を順番に評価して最後の引数の評価結果を返す」関数。元の式の最後にセミコロンが付くと値は何も出力されないが、これは、

CompoundExpression[Set[x, 3], Set[y, 5], Set[z, Plus[x, y]], Null]

であると理解される。 Null は欠損値を示すシンボルで、通常は出力されない。セミコロンによる出力抑制は、それが1行きりであっても CompoundExpression[exp, Null] だということだ。

これら、省略していない Set, SetDelayed, CompoundExpression などを使って書いた式を含むセルを選択して、[セル] メニュー > [形式変換] > [StandardForm (標準形)] を再実行すると、慣れ親しんだ省略表記になることを確認できる。

StandardForm にすると見慣れた省略表記になる

多くの言語で予約語の形で実装されている制御構造、つまり条件分岐やループが、Mathematica では関数として実装されていることは、みんなが気づいている通り。例えば、いわゆる Do ループと呼ばれるものも、次の形の関数として用意されている。

Do[<繰り返す式>, {<繰り返し条件>}]

つまり Do ループは、「第1引数の内容を、第2引数で指定した条件で繰り返し評価する」という動作の関数として実装されている。条件分岐の If も同様。そのため、Do や If における式と条件の区切りは、それが引数の区切りである以上コンマでしかあり得ない。

ふつう、 Apply 関数を学ぶときに、リストと呼ばれる { } で括ったデータ構造が内部的には List[...] であることに気づく。だが、この 頭部[引数, 引数, ...] の形式は、リストに限らず、グラフィックスも含めた、 Mathematica 言語全体にわたる原則だったのだ。

この原則は、「言語の予約語が少ない」というよりは、「言語の一貫性」とでも言った方がいい。 Set を一時的に Unprotect して、自前の用途に使うということは不可能ではないので、 Set だって(ふつう言うところの)言語の予約語とは違うと説明することもできるが、この原則の話は予約語の話とは別にした方が良さそうだ。

そしてこの原則は、僕が「Mathematica 語って美しいねぇ」と感じるものの根っこの方にあるものだ。そういうオタク性を抜きにしても、この原則を知っていることは、 Mathematica コードを書いたり、 MathLink を通じて外部から Mathematica を利用するのに、きっと助けになるだろう。

関連して最後にひとつコワザを紹介。
演算子や記号が何かの省略表記かもしれないと思ったときは、 ? または ?? を付けてその記号を評価してみよう。省略表記だった場合は、表示されるリンク先のヘルプページで省略でない正式名を知ることができる。

省略表記の対応している関数名を調べる

※この記事の内容は執筆者の個人的見解で、ヒューリンクスによる公式情報ではありません。[免責事項]

トラックバック

この記事へのトラックバックURL
http://blog.hulinks.co.jp/cgi/mt/mt-tb.cgi/425
内容に対しての関連性がみられないものは削除する場合があります

このたびの大震災で被災された方々を思うと、胸が苦しい。亡くなられた方々の冥福を祈... 続きを読む

今回は、Mathematica の即時定義と遅延定義について。これに関する今のバ... 続きを読む

たまに見る Mathematica の質問にこんなのがある。下記の書き方で、分母... 続きを読む

コメント一覧

いつも面白い話題をありがとうございます。
最初にMathematicaを使ったとき、コマンドとコマンドを繋ぐことができる、リスト対応に感激しました。
=と:=の違いが入力(In[]=)と出力(Out[]:=)のときにも表れているのに気がつくのは遅かったな。

藤村さん、いつもありがとうございます。
そうか。入力は未評価保持で、出力は評価したものを保持、という違いが In と Out の表記の違いの意味ですものね。機会があれば、この割り当ての話はもういちど書くかもしれません。
これからも、よろしくお願いします。

コメントの投稿

Emailアドレスは表示されません。は必須項目です。
ヒューリンクス取り扱い製品の内容や購入に関するお問い合わせはヒューリンクスサイト連絡先へお願いいたします。投稿前にその他の注意事項もご覧ください。

HULINKS サイトの新着情報