即時的な定義と遅延的な定義
Mathematicaで割当てを行うには,2つの違った方法があることに読者はすでに気が付いているかもしれない.つまり,
lhs=rhsと
lhs:=rhsである.これらの形の間にある基本的な違いは,いつ式
rhs が評価されるかにある.
lhs=rhsは即時型の割当てを表し,右辺
rhs は定義した時点で評価される.これに対して,
lhs:=rhs は遅延型の割当てを表し,
rhs は,割当てが行われるときには評価されず,
lhs の値が要求されるときに毎回評価される.
| lhs=rhs (即時型の割当て) | 右辺rhs は,定義時に評価される |
| lhs:=rhs (遅廷型の割当て) | 右辺rhs は,左辺lhs の値が要求されるときに毎回評価される |
2種類の割当て
演算子 =で割当てを行うと,右辺は即座に評価される.
| Out[3]= |  |
|
| Out[5]= |  |
|
iexは,その引数を展開済みの式に代入し, exとは違った答を返す.
| Out[6]= |  |
|
上の例から分かるように,
=と
:=はともに関数を定義する上で便利だが,違った意味を持っている.このため,状況に応じて使い分ける必要がある.
使い分けの目安として次の手順を取るとよい.割当てを,ある式の最終的な「値」を与えるものととらえるならば,演算子
=を使う.また,割当てを,値を見出すための「コマンド」としてとらえるならば,演算子
:=を使う.どちらかはっきりしないときは,通常,
=ではなく,
:=を使うと無難である.
| lhs=rhs | 右辺rhs は,左辺lhs の「最終値」(例:f[x_]=1-x^2) |
| lhs:=rhs | rhs は, lhs の値が要求されるときに実行される「コマンド」や「プログラム」を与える(例:f[x_]:=Expand[1-x^2]) |
演算子=と:=による割当て操作の解釈
関数の定義でおそらく,
:=は,
=より多く使われるだろうが,次に示す重要な場合には,必ず
=を使い関数を定義しなければならない.ある計算を行い,シンボル的パラメータ
x により答が得られるとき,
x を各種の特定値としたときに結果がどうなるかを調べる必要がよく出てくる.そのようなときは,ひとつの方法として,演算子
/.を使い,
x について適切な規則を適用することが考えられる.しかし,通常は,
=を使い,引数を
x とした関数を定義した方がより便利になる.
| Out[7]= |  |
|
| Out[8]= |  |
|
| Out[9]= |  |
|
上の例において重要な点は,パターン
x_に現れる名前
xは特別な意味を持たないということである.他の任意の式に現れる
xと同様に,単なるシンボルでしかない.
| f[x_]=expr | x が特定値を取るときに値expr を返す関数を定義する |
式を評価するための関数の定義
=と
:=は,関数定義だけでなく変数への値の割当てにも使うことができる.
x=value と入力すれば,値
value は即座に評価され,結果は
x に割り当てられる.一方,
x:=value と入力すると,
value はすぐには評価されない.入力されたままの形で維持され,実際に,
x が使われるときに毎回再評価される.
| Out[10]= |  |
|
| Out[12]= |  |
|
r1の値は変わらない.しかし, r2が使われると,その都度,新たな乱数が生成される.
| Out[13]= |  |
|
数珠つなぎに割当て関係を構築していく際は,即時型の割当てと遅延型の割当ての間にある違いは,特に重要である.
| Out[14]= |  |
|
a+2が評価され,結果 3が riの値として割り当てられる.
| Out[15]= |  |
|
a+2は評価されないまま保持される. rdの値が要求されると,そのたびに再評価される. |
値を確認する.この時点で, riと rdは同じである.
| Out[17]= |  |
|
| Out[18]= |  |
|
rdには新たな aの値が使われるが, riは古い値のままである.
| Out[19]= |  |
|
t:=rhs の遅延型の割当てを使えば,変化する「状況」に応じた値を右辺
rhs に割り当てることができる.
t を参照するときは,その都度,それが依存するオブジェクトの最新値が使われて右辺
rhs が再評価される.
| Out[21]= |  |
|
| Out[22]= |  |
|
上の例で,シンボル
aは
tの値を左右する「大域変数」として働く.パラメータをたくさん使う必要があり,また,それらの値をあまり変える必要がなければ,この割当て方法は便利でよいだろう.しかし,変数が他の変数への隠された依存性を持つようなときは,この方法で変数の割当てを行うとかえって混乱させるかもしれないので注意が必要である.関数を定義する際に,必要なすべてのパラメータを引数とすることで,依存性を明示化しておいた方がよい.
| lhs->rhs | 右辺rhs は規則の定義時に評価される |
| lhs:>rhs | 右辺rhs は規則が使われるときに評価される |
2種類の変換規則
割当てに,即座に行うものと,後で行うものの2種類があるように,変換規則にも即時型と遅延型がある.
| Out[23]= |  |
|
このような規則は実用的な価値がないが,入力してみる.
| Out[24]= |  |
|
規則の右辺は未評価の形のまま保持される.規則が使われるときに毎回評価される.
| Out[25]= |  |
|
この規則を適用させると,初めて右辺の式が展開される.
| Out[26]= |  |
|
割当ての場合と同じように,置換する値が確定しているときは,
->を使うようにし,また,式の値を求めるためのコマンドを与えるときには,
:>を使うようにする.