モジュールの動作の仕方

モジュールの動作は基本的に非常に単純である.モジュールが使われると,その都度,新規のシンボルが生成されモジュールの必要とする局所変数が表される.新規シンボルには,固有の名前が与えられる.名前は他のシンボル名と競合しないようにされる.つまり,ユーザにより指定された名前には記号と固有の「シリアル番号」が加えられる.

このシリアル番号は,大域変数$ModuleNumberの値をもとに内部で生成される.この変数は,Module式がこれまでに使われたすべての使用回数を数えるためにある.

Moduleは,各局所変数を表すために書式 x$nnn の名前を持つシンボルを生成する.

モジュール局所変数の内部参照名

モジュールにおいてに対して生成されるシンボルが表示される.
同じ名前を使っても,別のモジュールなら内部の名前は別なものになる.

通常の計算で,内部定義されるモジュール変数の名前を使うことはまずないであろう.しかし,モジュールを評価する際のダイアログ(カーネルとの対話)の開始とか,トレース機能を使ったモジュール内における各評価ステップのTrace では,内部定義の変数名が表示に使われることがある.

Traceを使うと,モジュール内で生成されるシンボルを見ることができる.
In[3]:=
Click for copyable input
Out[3]=
モジュールの中からダイアログを開始させる.
In[4]:=
Click for copyable input
ダイアログの中では,のような局所変数に対して生成されたシンボルを表示させることができる.
In[5]:=
Click for copyable input
Out[5]=
これらのシンボルは,これまでの他のシンボルと同様に扱うことができる.
In[6]:=
Click for copyable input
Out[6]=
ダイアログから戻る.
In[7]:=
Click for copyable input
Out[7]=

場合によっては,モジュール内で生成されたシンボルを戻り値として出力することができると便利である.

モジュール内で生成されたシンボルを返すよう指示する.
In[8]:=
Click for copyable input
Out[8]=
返されたシンボルはこれまでの他のシンボルと同じように扱うことができる.
In[9]:=
Click for copyable input
Out[9]=
Unique[x]書式 からなる固有な名前を持つ新規のシンボルを作る
Unique[{x,y,}]リスト指定される複数の新規シンボルを作る

固有名を持つ新規のシンボルの生成

関数Uniqueを使うと,Moduleの場合と同じようにシンボルを新規に生成することができる.Uniqueが呼び出されるたびに,$ModuleNumberが増分されるため,新たに作られるシンボルは必ず固有の名前を持つようになる.

で始まる名前を持つ固有のシンボルが新たに作られる.
In[10]:=
Click for copyable input
Out[10]=
Uniqueが呼び出されるたびに,シリアル番号が1大きくなり,違う名前のシンボルが1つ得られる.
In[11]:=
Click for copyable input
Out[11]=
複数の名前のリストを使いUniqueを呼び出すと,作られるすべてのシンボルには同一のシリアル番号が与えられる.
In[12]:=
Click for copyable input
Out[12]=

?name の標準書式を使うことで,モジュールの中や関数Uniqueで作成されたシンボルに関する情報を得ることができる.

このモジュールは, 形式のシンボルを生成する.
In[13]:=
Click for copyable input
Out[13]=
生成された変数を参照する.

Moduleで生成されたシンボルは,評価の目的において,他のシンボルと全く同様に機能する.しかし,これらのシンボルは,有効性を一時的にする属性Temporaryを持つため,使用されなくなった時点で消去される.モジュールの中で生成されるほとんどのシンボルは,そのモジュールの実行が完了する時点で除去される.例外として,戻り値として返されるシンボルだけは生き残る.

モジュールの中で生成された新規の変数が表示される.
新たに作られた局所変数は,モジュールの実行が終了した時点で除去される.このため,を参照することはできない.

形式による名前の付け方は単なる規約である.ユーザ自身でこの形式を使いシンボルに名前を付けることもできる.ただし,そうして作成されたシンボルは,Moduleで生成されたものと競合してしまうかもしれない.

重要な点は,Moduleにより生成されるシンボルは,通常,現行のセッションだけで有効であることである.シリアル番号を決定するためのパラメータ$ModuleNumberは常に新たなセッションが開始されるときに再設定される.

このため,特に,生成されたシンボルを含んだ式をファイルに保存し,それらの式を別のセッションに読み込ませるとき,競合が起らないという保証は何もない.

この競合を防ぐには,ひとつの方法として,各セッションの開始時に$ModuleNumberを異なった値に設定しておく.例えば,$ModuleNumber=10^10 $SessionIDと設定しておくと,必ず競合を防ぐことができる.大域変数である$SessionIDは,Wolfram言語のセッションと使用するコンピュータの機種番号に依存した数値を保持する.この変数の値は,絶対的な日付や時刻やコンピュータの識別番号,さらに,必要ならば現行のWolframシステムプロセスの識別番号をもとに決定される.

$ModuleNumberModuleUniqueにより生成されるシンボルに対するシリアル番号
$SessionIDWolfram言語セッションごとに変わる番号

固有名を決定する大域変数

Module[vars,body]は,指定された局所変数を表すためのシンボルを生成すると,次に,これらのシンボルを適用することで本体式 body を評価していく.取られる第1ステップは,実際の式 body をモジュール内に現れる通りの形で抽出し,そして,Withを実行的に適用することで,各局所変数を適切な内部生成されたシンボルで置換している.このステップが終り次第,Moduleは,結果として得られた式を実際に評価する.

注意点として,Module[vars,body]は,内部生成されたシンボルを実際の式 body だけに挿入する.内部生成されたシンボルは body から呼び出されるが,body に具体的に現れないコードには挿入されない.

「ブロックと局所値」で説明するが,Blockを使うことで,これとは異なった働き方をする「局所値」を設けることができる.

はモジュール本体に具体的に現れないので,その局所値は使われない.
In[17]:=
Click for copyable input
Out[17]=

多くの場合,モジュールの設置は,書式Module[vars,body]に従って記述された明示的なWolfram言語への入力を使うことで行われるだろう.関数Moduleには属性HoldAllが付加されているので,実際にモジュールが実行されるまでは,本体 body は未評価のまま保持される.

ただし,モジュールを動的に構築することは可能である.新たなシンボルの生成や,それらの body への挿入は,モジュールが実際に実行されるときに初めて行われる.モジュールがWolfram言語への入力として与えられるときではない.

モジュールの本体式が即座に評価され,先に定義したが現れる.
In[18]:=
Click for copyable input
Out[18]=