モジュール構成と変数名の付け方

モジュールと局所変数
Wolfram言語では,ユーザ定義の変数は通常大域的なものとみなされる.このため,同じ名前,例えば,xが入力されるたびに,それは同一のオブジェクトを参照するためのものとされる.
しかし,特にプログラムの記述においては,必ずしもすべての変数を大域的なものとはしたくないことがある.例えば,同じxの名前を使い,2つのプログラムにある別々の2つの変数を参照したいかもしれない.このようなときは,xを各プログラムにおいて局所変数として扱われるようにしておく必要がある.
Wolfram言語では,モジュールを使うことで局所変数の定義を行うことができる.モジュールの中に与えられた変数は,モジュール内だけで有効な局所変数として扱われる.
Module[{x,y,},body]
局所変数 x, y, を備えたモジュール
モジュールの作成
大域変数tへの値17の割当てを定義する:
モジュール中のtは局所化されている.このため,先に作った大域変数のtとは独立に扱うことができる:
大域なtの値は17のままである:
モジュールの最も一般的な使いみちは,定義したい関数の中で一時的(臨時的)な変数を設けることである.そのような変数はモジュール内だけで有効な局所変数にしておくことが重要である.局所変数にしておかないと,同じ参照名を持つ変数が外部にある場合,競合してしまい思いも寄らない間違いを引き起してしまう.
臨時変数tはモジュールに局所になるように指定される:
関数fを実行させる:
大域変数tの値は17のままである:
モジュール内では,局所変数はいわゆる変数だけでなく他のシンボルと同じように使うことができる.例えば,局所関数の名前として使うことができる.また,局所変数に属性を割り当てることもできる.
局所関数fを定義するモジュールを作る:
この局所関数fは単なる普通の一階乗である:
このfは,一般化された階乗として機能する:
あるモジュールで局所変数が設けられるとき,Wolfram言語はその変数に対しての値の割当ては行わない.このため,モジュールの外に同じ名前の大域変数がすでにあったとしても,それを純粋なシンボルとして使うことができる.
上の例で定義したtの大域値が使われる.このため,ある数が返される:
ここで,Lengthは単に1つの数を引数として受け取る:
局所変数tには値が割り当てられていないので,シンボルとして扱われる.このため,Expandは,想定された代数式的な結果を生成する:
Module[{x=x0,y=y0,},body]
モジュールの局所変数に初期値を割り当てる
局所変数の初期化
tを局所変数とし,初期値uを割り当てる:
gの定義を使う:
初期値の定義はモジュールのどの局所変数に対してでも行うことができる.初期値は常にモジュールが実行される前に評価される.このため,モジュールに対して局所的に定義された変数xがあっても,名前xがある初期値の設定を行うための式に現れるときは,大域のxが使われる.
uの初期値はtの大域値とされる:
lhs:=Module[vars,rhs/;cond]
右辺 rhs と条件式 cond の間で局所変数を共有する
条件付き定義における局所変数の使用
ある定義に対して/;条件式を設ける際は,一時的な変数を導入する必要がよく出てくる.多くの場合は,一時変数を定義の右辺にある本体式とで共有できるようにしたい.このような共有を行うには,条件式を含める形で定義の右辺をモジュールの角カッコに入れておく.
関数を条件付きで定義する:
局所変数tの値は,条件式と右辺の本体式で共有される:
局所定数
With[{x=x0,y=y0,},body]
局所定数 x, y, を定義する
局所定数の定義
Moduleを使うと局所変数を設定し,それに値を割り当て.変更することができる.しかし,多くの場合,本当に必要なものは一度だけ値が割り当てられる局所定数だけである.Wolfram言語では,局所変数の設置は構成体Withを使い行うことができる.
tに対し大域値を定義する:
tを局所定数として使い関数を定義する:
wの定義が適用される:
tは最初に割り当てられた大域値のままである:
Moduleにおいてそうであったように,Withにおいても,そこで定義される初期値はWithが実行される前に評価される.
局所定数tの値を与える式t+1は大域のtが使われ評価される:
With[{x=x0,},body]の機能の仕方としては,まず,body が取り出され,次に,式中に現れる x 等の各オブジェクトがそれに対応した値 x0等で置換される.Withは一般化された演算子/.ととらえることができ,式でなくWolfram言語コードに適している.
xaに置換する:
置換後は,Withの本体式はa=5になり,aには値5が割り当てられる:
aの値を消去しておく:
見方によっては,Withは局所変数が必ず1回しか値が割り当てられないModuleの特殊ケースのようなものである.
Withを使う1つの大きな理由は,多くの場合,Moduleより読みやすい計算プログラムを書くことができるからである.Moduleを使うとすると,局所変数(例えば,x)の値を確認するには,x が参照されるたびに,そこまでの式をすべてトレースしなければならない.その点,Withを使うと,どこに x があってもその値は同じなので,単に初期値を見るだけでよい.コードをトレースする必要はない.
複数のネストされたWith構成体があるとき,同じ参照名の局所変数が複数存在してしまう場合がある.そのときは,常に,最も内側の部分に置かれた変数の定義が有効とされる.ModuleWithは混ぜて使うことができる.そのときも,一般則として,有効とされる変数は最も内側の変数である.
ネストされたWith構成体で有効とされる変数は最も内側のものである:
ModuleWithの構成体は混ぜて使うこともできる:
内側の構成体にある局所変数が外側にある変数を隠すようなことはない.変数名が同じ場合はその限りではない:
xbody がいつ評価されるかの問題を除けば,With[{x=x0,},body]は,基本的に式 body/.x->x0と同様に機能する.しかし,body に別のWith式やModule式があるとき,Withは特殊な動作を取る.ここで重要な点は,Withにある局所定数の間と,そして局所定数と大域オブジェクトの間で競合が起らないようにすることである.実際にどうすればこれができるかは「モジュールの動作の仕方」を参照のこと.
内側のWithにあるyは名前が変更され,大域のyと競合しないようにされる:
モジュールの動作の仕方
モジュールの動作は基本的に非常に単純である.モジュールが使われると,その都度,新規のシンボルが生成されモジュールの必要とする局所変数が表される.新規シンボルには,固有の名前が与えられる.名前は他のシンボル名と競合しないようにされる.つまり,ユーザにより指定された名前には$記号と固有の「シリアル番号」が加えられる.
このシリアル番号は,大域変数$ModuleNumberの値をもとに内部で生成される.この変数は,Module式がこれまでに使われたすべての使用回数を数えるためにある.
Moduleは,各局所変数を表すために書式 x$nnn の名前を持つシンボルを生成する.
モジュール局所変数の内部参照名
モジュールにおいてtに対して生成されるシンボルが表示される:
同じ名前を使っても,別のモジュールなら内部の名前は別なものになる:
通常の計算で,内部定義されるモジュール変数の名前を使うことはまずないであろう.しかし,モジュールを評価する際のダイアログ(カーネルとの対話)の開始とか,トレース機能を使ったモジュール内における各評価ステップのTrace では,内部定義の変数名が表示に使われることがある.
Traceを使うと,モジュール内で生成されるシンボルを見ることができる:
モジュールの中からダイアログを開始させる:
ダイアログの中では,tのような局所変数に対して生成されたシンボルを表示させることができる:
これらのシンボルは,これまでの他のシンボルと同様に扱うことができる:
ダイアログから戻る:
場合によっては,モジュール内で生成されたシンボルを戻り値として出力することができると便利である.
モジュール内で生成されたシンボルを返すよう指示する:
返されたシンボルはこれまでの他のシンボルと同じように扱うことができる:
Unique[x]
書式 x$nnn からなる固有な名前を持つ新規のシンボルを作る
Unique[{x,y,}]
リスト指定される複数の新規シンボルを作る
固有名を持つ新規のシンボルの生成
関数Uniqueを使うと,Moduleの場合と同じようにシンボルを新規に生成することができる.Uniqueが呼び出されるたびに,$ModuleNumberが増分されるため,新たに作られるシンボルは必ず固有の名前を持つようになる.
xで始まる名前を持つ固有のシンボルが新たに作られる:
Uniqueが呼び出されるたびに,シリアル番号が1大きくなり,違う名前のシンボルが1つ得られる:
複数の名前のリストを使いUniqueを呼び出すと,作られるすべてのシンボルには同一のシリアル番号が与えられる:
?name の標準書式を使うことで,モジュールの中や関数Uniqueで作成されたシンボルに関する情報を得ることができる.
このモジュールは,q$nnn 形式のシンボルを生成する:
生成された変数を参照する:
Moduleで生成されたシンボルは,評価の目的において,他のシンボルと全く同様に機能する.しかし,これらのシンボルは,有効性を一時的にする属性Temporaryを持つため,使用されなくなった時点で消去される.モジュールの中で生成されるほとんどのシンボルは,そのモジュールの実行が完了する時点で除去される.例外として,戻り値として返されるシンボルだけは生き残る.
モジュールの中で生成された新規の変数qが表示される:
新たに作られた局所変数は,モジュールの実行が終了した時点で除去される.このため,qを参照することはできない:
x$nnn 形式による名前の付け方は単なる規約である.ユーザ自身でこの形式を使いシンボルに名前を付けることもできる.ただし,そうして作成されたシンボルは,Moduleで生成されたものと競合してしまうかもしれない.
重要な点は,Moduleにより生成されるシンボルは,通常,現行のセッションだけで有効であることである.シリアル番号を決定するためのパラメータ$ModuleNumberは常に新たなセッションが開始されるときに再設定される.
このため,特に,生成されたシンボルを含んだ式をファイルに保存し,それらの式を別のセッションに読み込ませるとき,競合が起らないという保証は何もない.生成されたシンボルは一般的に一時的なものなので,実際にはあまり起こらない.競合に対処する方法として,一時的なシンボルが読み込まれるセッションの最初に,大きい値に$ModuleNumber(例えば2^($SystemWordLength-8))を手動で設定するというものがある.
Module[vars,body]は,指定された局所変数を表すためのシンボルを生成すると,次に,これらのシンボルを適用することで本体式 body を評価していく.取られる第1ステップは,実際の式 body をモジュール内に現れる通りの形で抽出し,そして,Withを実行的に適用することで,各局所変数を適切な内部生成されたシンボルで置換している.このステップが終り次第,Moduleは,結果として得られた式を実際に評価する.
注意点として,Module[vars,body]は,内部生成されたシンボルを実際の式 body だけに挿入する.内部生成されたシンボルは body から呼び出されるが,body に具体的に現れないコードには挿入されない.
「ブロックと局所値」で説明するが,Blockを使うことで,これとは異なった働き方をする「局所値」を設けることができる.
xはモジュール本体に具体的に現れないので,その局所値は使われない:
多くの場合,モジュールの設置は,書式Module[vars,body]に従って記述された明示的なWolfram言語への入力を使うことで行われるだろう.関数Moduleには属性HoldAllが付加されているので,実際にモジュールが実行されるまでは,本体 body は未評価のまま保持される.
ただし,モジュールを動的に構築することは可能である.新たなシンボルの生成や,それらの body への挿入は,モジュールが実際に実行されるときに初めて行われる.モジュールがWolfram言語への入力として与えられるときではない.
モジュールの本体式が即座に評価され,先に定義したxが現れる:
純関数と規則で使う変数
ModuleWithを使えば,名前を局所的なものとした特定のシンボルをリストで一括に与えることができる.しかし,場合によっては,特定のシンボルを自動的に局所とすることができると便利である.
例えば,Function[{x},x+a]のような純関数を使うとき,x は,局所的な特定の名前を持つ「仮パラメータ」として扱いたい.同じことは,f[x_]->x^2のような規則や,f[x_]:=x^2のような定義に現れるx に対しても言える.
Wolfram言語では一律の処理法が取られるので,純関数のような構成体に現れる仮パラメータは常に局所化された名前を持つ.したがって,大域的な名前と競合することはない.基本的な考えとしては,必要ならば,形を x$とする名前を持つシンボルで仮パラメータを置換する.規約に従い,x$は大域変数として使ってはいけない.
ネストされた純関数を定義する:
内側の関数で使われる仮パラメータ y は名前を変更され,大域オブジェクト y と競合しないようになる:
結果の純関数は期待通りの動作をする:
Function[vars,body]のようなオブジェクトで使われる仮パラメータは,body が他の純関数の動作により変更されるたびに別の名前に変えられる.
内側の純関数の本体式が変更したため,仮パラメータ y は名前が変更される:
今度は,内側の関数の本体式は変更しない.このため,仮パラメータの名前は変更されない:
純関数で仮パラメータを使うと,その名前は変更されると説明したが,そのような処理は場合によっては不必要である.基本的に,純関数において仮パラメータの名前が純関数の本体式に代入される式の部分と競合しなければ,特に名前を変更する必要はない.しかし,一律性を維持するため,必要ないときも,仮パラメータの名前は変更される.
この例では,内側の関数にある仮パラメータ x が関数の本体式をシールドしているので,名前の変更は必要ない:
3回ネストされた関数を作る:
2つの内側の関数はともに名前が変更される:
「純関数」で説明したように,Wolfram言語の純関数は形式論理で使われる 式のようなものである.Wolfram言語では,仮パラメータに対しての名前の変更を行うことで標準 式の機能をすべて実現可能にしている.
Function[{x,},body]
局所パラメータ
lhs->rhs
and
lhs:>rhs
局所パターン名
lhs=rhs
and
lhs:=rhs
局所パターン名
With[{x=x0,},body]
局所定数
Module[{x,},body]
局所変数
スコープ限定構成体
Wolfram言語には,いくつかの「スコープ(有効範囲)限定のための構成体」を備えている.これらを使うことで,特定の名前を局所化することができる.また,これらの構成体が混ぜて使われるとき,Wolfram言語は,競合を防ぐように適切な名前の変更を行う.
競合を防ぐため,純関数で定義した仮パラメータは名前が変更される:
内側のWithにある局所変数は名前が変更され競合しないようになる:
この例では,競合がないので名前の変更はされない:
モジュールにある局所変数 y は名前が変更されて競合しないようになる:
しかし,このモジュールを実行させると,局所変数は再び,固有の名前に変更される:
変換規則はスコープを限定するための構成体として扱われ,そこに与えられるパターンに対する名前は局所的な性格を持つ.名前付きのパターンは,x_x__x:patt 等を使い作成することができる.
h にある xx_に適合する.このため,規則から見ると局所的なものになる:
f[x_]->x+yのような規則では右辺に現れる x は引数パターンx_に適合する.このため,x は規則に対して局所的な変数として扱われる.したがって,別の構成体で x を別のスコープに変更することはできない.
これに対して,y は規則から見ると局所的なものではないので,別の構成体でそのスコープを変更することが可能である.Wolfram言語は,競合を避けるためこの規則にあるパターンの名前を変更する.
規則にある x は名前が変更され,競合しないようにされる:
スコープを限定する構成体にWithを使うと,Wolfram言語は自動的に適切な名前の変更を行う.しかし,場合によっては,名前の変更をせずに,スコープを限定する構成体の中において代入操作を行いたい.そのようなときは演算子/.を使う.
Withを使い y の代入を行うと,純関数にある x は適当な名前に変更され競合しないようにされる:
Withの代りに/.を使うと,名前の変更は行われない:
f[x_]->rhs のような規則や,f[x_]:=rhs のような定義が適用されると,Wolfram言語は,右辺 rhs にあるすべての x に対して代入操作を施す.この代入操作は,演算子/.が実効的に使われて行われる.このため,この代入では,スコープ構成体によるスコープが効かなくなってしまう.ただし,あるスコープ構成体の内部のオブジェクトが代入操作により変更されるときは,そのスコープ構成体にある他の変数は名前が変更される.
純関数を生成するための関数を作る
演算子/.が実効的に使われ,xx^2は純関数に挿入される:
今度は,ペアのネストされた純関数を生成するための関数を作る:
外側の純関数にある x は名前が変更される:
数学のダミー変数
数学の理論式を構築する際には,各種の局所化されたオブジェクト,つまり,「ダミー変数」を導入する必要がでる.ダミー変数は,モジュールや他のスコープを限定するための構成体を使うことで作成することができる.
数学のダミー変数の代表的なものに積分変数がある.形式的な積分を記述するとき,慣用の表記法では,特定名を持つある積分変数を導入する必要がある.この変数は,基本的に積分に「局所的」とされる.また,ダミー変数の名前は,任意の名前で構わないが,数式にある他の名前と競合してはならない.
ある積分を評価するための関数を定義する:
この例のs は積分変数と競合してしまう:
これは,モジュールに対して局所化された積分変数の定義である:
モジュールが使われたので,Wolfram言語は名前を自動的に変更し,競合を防ぐ:
多くの場合,ダミー変数は局所なままにしておき,数式の他の変数に干渉しないようにしておきたい.しかし,場合によっては,同じダミー変数を違った用途で使うときに,用途間で競合しないようにすることがより重要になる.
ベクトルやテンソルの積を構築する式では,ダミー変数を繰り返し使う必要が出てくる.「和の規約」にならうと,ちょうど2回現れるベクトルやテンソルの添数には,その添数の取り得る限りの値の中で総和が取られる.繰り返し使われる添数の実際の名前は何でも構わないが,もしも,繰り返し使われる添数が2つあるならば,競合しないような名前にしておく必要がある.
繰り返し使われる添数 j をダミー変数として設ける:
モジュールは,ダミー変数の各インスタンスに対して別の名前を与える:
数学のいろいろな場面で,固有名を持つ変数を使う必要が出てくる.例えば,方程式の解を表すときがそうである.のような方程式には, の形の解は無限に存在する.ここで, はダミー変数であり,値は整数であれば何でもよい.
Wolfram言語は,次の方程式を解く際にダミー変数を作る:
次は,ダミー変数を一意的にするための方法である:
固有のオブジェクトが必要となるもうひとつの場面は「積分定数」を表すときである.積分を行うということは,実効的に導関数に関して方程式を解くことに相当する.一般に,方程式にはいくつもの可能な解が存在し,各解は加法的な「積分定数」により他の解と異なる.標準的なWolfram言語の積分関数Integrateは,常に,積分定数を付加しないで解を返すようになっている.しかし,ユーザ自身で,積分定数を導入すれば,モジュールを使い各定数を固有化しておく必要がある.
ブロックと局所値
モジュールを使うことで,変数の名前を局所的なものとして扱うことができる.場合によっては,変数の参照名は大域的なものとしておき,変数の取る値だけを局所化したい.これを行うにはBlockを使う.
Block[{x,y,},body]
局所値 x,y,を使い body を評価する
Block[{x=x0,y=y0,},body]
x,y,に初期値を割り当てる
ブロックを使った局所値の設定
x を使った式を入力しておく:
入力した式を評価させる.x には局所的な値が使われる:
x には何も大域的な値は割り当てられていない:
「モジュールと局所変数」で説明してあるように,Module[{x},body]において,変数 x は常に固有な名前を参照するように設定される.つまり,モジュールが使われるたびに固有とされ,また,大域変数 x からも固有とされるように x は名前が変更される.これに対して,Block[{x},body]では,x は大域的なスコープ x とされる.ただし,x の取る値は局所的なものとされる.したがって,ブロックが終了すると,x には昔の値が戻される.ブロック内ではどんな値でも割り当てることができる.
シンボル t に値17を割り当てる:
モジュール内の変数は固有の局所名を持つ:
ブロックでは,変数の大域名は維持されるが,変数の値は局所的なものでもよい:
ブロックにおいて,t には局所値が割り当てられる:
ブロックの実行が終ると,もとの値が t に戻される:
ブロックを使うと,実効的に「局在化された環境」を作り出すことができる.この環境では変数の値を一時的に変更することができる.あるブロックの実行中に評価される式は,そのブロックにある変数に対して現時点で定義されている現行値を使う.同じことは,ブロックで直接記述される本体の各式だけでなく,各式の評価により生成される式についても言える.
シンボル u に対して遅延型の値を定義する:
ブロックの外で u を評価させると,t に対する大域値が使われる:
t に対して,ブロック内での使用のための一時的な値を指定することもできる:
DoSumTable等の反復処理を行う構成体ではBlockが使われる.これらの構成体では,実効的にBlockの機構が使われ反復変数がすべて局所的な値を持つものとして扱われている.
Sumを作用させると,自動的に反復変数 t の値が局所的なものにされる:
反復構成体における局所値化はBlockより多少だが一般化されている.つまり,a[1]や純粋な変数も局所値化の対象になる:
直接引数としては与えられないが,関数の動作には影響を与える,という働きを持つ大域変数が使えると便利な場合がある.一例として,帰納的な反復回数の上限を決定するための大域変数$RecursionLimitがある.この変数はすべての関数の評価に影響を及ぼすが,関数の直接の引数としては働かない.
大域変数に一度値が割り当てられると,特別に変更されるまでは,その値は変わらない.場合によっては,特定の計算だけとか計算の一部分だけで値を有効としたいときもある.それを行うにも,ブロックを使うことができる.
「大域変数」t に依存する関数を定義する:
この場合,t の大域値が使われる:
ブロックの中では t に対して局所値を設けることもできる:
大域変数を使い,関数のパラメータへの値の割当ての他に,関数からの結果の蓄積を行うこともできる.つまり,大域変数をあるブロックに対して局所化しておくことで,ブロックから呼び出される関数からだけの結果を蓄積させることができる.
この関数は,大域変数t を増分し,その現行値を返す:
ブロックを使わないでh[a]を評価させると,t の大域値を変更する:
ブロックを使うと,t の局所値だけが変わる:
t の大域値は同じままである:
Block[{x},body]等のブロックが評価されるときは,x に割り当てられている現行値が除去される.このため,理論上は,ブロックの中では x を実質的な「シンボル的な変数」として扱うことができる.しかし,x を戻り値としてブロックから返すと,それはブロック評価前の外部の値により置換されてしまう.
ブロックを評価させると,t の現行値は除去される:
t を含む式を戻り値とすると,t の大域値が使われ式の評価が行われる:
ブロックとモジュールの比較
Wolfram言語でプログラムを記述するとき,構成部分(計算式等)をなるべく独立した形で書くことが大切である.各部分を独立させて書くことで,保守や補修がやりやすいプログラムを構築することができる.
独立型のプログラムを書く上でよく取られる方法は,使う変数のスコープ(適用範囲)を限定する方法である.これは,基本的にモジュールとブロックを使い行う.
実際のプログラムを書くとき,モジュールはブロックより多く使われる.しかし,対話的な計算ではスコープ指定が必要となるため,ブロックを使った方が便利なことがよくある.
Module[vars,body]
レキシカルなスコープ限定
Block[vars,body]
ダイナミックなスコープ限定
スコープ限定の対象
ほとんどの従来型のプログラミング言語では,いわゆる「レキシカルなスコープの限定法」が使われ変数の有効範囲を指定するようになっている.この方法はWolfram言語のモジュールに相当する.シンボル処理系の言語にLISPがあるが,そこでは,「ダイナミックなスコープの限定」もできるようになっている.これは,Wolfram言語のブロックに相当している.
レキシカルな限定を行うと,変数の参照名は局所化され,プログラムコードの一部分だけでしか参照することができないようになる.これに対して,ダイナミックな限定を行うと,局所化は変数の値に対して行われ,値はプログラム実行における時間的な履歴の一区間だけで有効になる.
CやJavaのようなコンパイル系の言語ではコード体系と実行履歴体系をはっきりと区別することができる.シンボル処理系のWolfram言語では,この境界はやや曖昧である.それというのも,Wolfram言語では実行中のプログラムからダイナミックにコードを生成することも可能だからである.
モジュールModule[vars,body]を使うと,このモジュールがWolfram言語プログラムのコードとして実行されるときに初めて式 body が処理の対象になる.モジュールは式を調べ,変数 vars のいずれかが,明示的にコードに現れた時点で初めて局所化される.その後通常の評価が行われる.
ブロック式Block[vars,body]では式 body の形は無視される.その代り,それぞれの vars の現行の値が記録される.式 body が評価される間は vars の値はずっと局所的なものとされ,body の評価が終了するともとの値に戻される.
miの式を割り当てる:
このブロックのi+mの計算では,iには局所値が使われる:
モジュールでは,i+mで現れるiだけが局所変数として扱われる:
コンテキスト
変数名と関数名は,できるだけ具体的な名前にした方がよい.しかし,あまり長いのも考えものである.
Wolfram言語では,「コンテキスト」と呼ばれる考え方が使われシンボルの名前を構成することができるようになっている.コンテキストは,Wolfram言語のパッケージを使うときに特に重要で,あるパッケージで導入されたシンボルの名前が他のシンボルの名前と競合しないようにするために使われる.ユーザ自身でパッケージを記述する場合や,市販パッケージの中身を変更するような場合には,コンテキストについて詳しい知識を持つ必要がある.
対象になるオブジェクトが何であれ,その正式名称は必ず2つの部分からなる.すなわち,完全名はコンテキスト名と簡略名(いわゆる名前)からなり,「context`short」の書式で記述される.Wolfram言語において,記号`は(ASCII文字コード番号は10進数の96)コンテキストマークと呼ばれる.
一例として,コンテキストがaaaaで簡略名がxからなるシンボルの正式名を作ってみる:
今作ったシンボルを使ってみる.他のシンボルと同様に使うことができる:
このシンボルには,どんな値でも定義することができる:
a`xb`xは全く別のものとして扱われる:
定義したいシンボルの種類に依存してコンテキストを使い分けるとよい.例えば,物理単位を表したシンボルには,特別なコンテキストPhysicalUnits`を使ったりすることができる.そうすると,単位記号の完全名はPhysicalUnits`Joule(ジュール)とかPhysicalUnits`Mole(モル)とかになる.
完全名を使わなくても,普通は,短くて便利な簡略名だけで間に合う.
現行セッションの任意位置において,現行のコンテキスト$Contextは必ず1つだけある.シンボルが$ContextPath上の同じ短縮名を持つシンボルで隠されていない限り,そのコンテキストにあるシンボルはその簡略名を使うだけで参照することができる.
Wolfram言語セッションにおけるデフォルトのコンテキストはGlobal`(大域)である:
Wolfram言語セッションにおけるデフォルトのコンテキストはGlobal`(大域)である:
Wolfram言語のコンテキストは,いくつかの面で,多くのオペレーティングシステムで使われているファイルのディレクトリに似ている.例えば,ファイルを指定するには,ファイル名とディレクトリ名を一緒に指定すれば確実にできる.しかし,常に現行の作業ディレクトリが存在しており,それが現行のWolfram言語コンテキストに相当する.そのディレクトリにあるファイルなら,いちいちディレクトリ名を指定する必要はない.
多くのオペレーティングシステムにおけるディレクトリがそうであるように,Wolfram言語のコンテキストも階層構造を取っている.例えば,シンボルが3つのコンテキストからなる階層位置に置かれている場合,その正式名は,c1`c2`c3`name となる.
context `name
または
c1`c2
`name
絶対指定コンテキスト
`name
現行コンテキスト
`context`name
または
`c1`c2
`
`name
相対指定コンテキスト
name
相対指定コンテキスト
コンテキストの指定法
コンテキストa`b`においてシンボルを作る:
Wolfram言語のセッションが始まる時点では,コンテキストはGlobal`(大域的)にされる.普通は,このコンテキストにオブジェクトを作成していくことになる.例外として,Pi等の組込み定数はSystem`(システム)コンテキストに定義される.
Global`だけでなく,System`のようなよく使われるコンテキストは特別な操作なしで使うことができると便利である.そこで,Wolfram言語ではコンテキストの検索パスと呼ばれるオブジェクトが提供されている.Wolfram言語のセッションでは,現行コンテキストはパラメータ$Contextに登録される.検索パスは$ContextPathに保持される.コンテキスト名が検索パスにあれば,そのコンテキストにあるオブジェクトを参照するときに特にそのコンテキストを指定する必要はない.簡略名だけで指定できる.
Wolframシステムのシンボルに対するコンテキスト検索パスは,プログラムファイルを探すためのオペレーティングシステム上の検索パスに相当する.$Context$ContextPathの後に検索されるため,ファイルの検索パスに「.」が加わったものと考えることができる.
コンテキスト検索パスにはシステムコンテキストも含まれている:
Piのコンテキストはシステム(System`Pi)である:
Context[s]
シンボルのコンテキスト
$Context
現行セッションにおける現行コンテキスト
$ContextPath
現行コンテキスト検索パス
$ContextAliases
コンテキストのエイリアスのリスト
Contexts[]
すべてのコンテキストのリスト
コンテキスト関連の機能
違うコンテキストならば,簡略名は同じであっても構わない.例えば,物理単位コンテキストPhysicalUnits`と生物コンテキストBiologicalOrganisms`と呼ばれるコンテキストを作ったとする.すると,そのどちらのコンテキストにも,Moleの同一名でシンボルを作成することができる.
それでは,簡略名Moleだけを指定すると,どちらの変数が実際に選択されるだろうか.検索パスのリストでより先に指定してあるコンテキストが優先される.
簡略名をMoleとするコンテキストが違う変数を2つ作成する:
$ContextPathに使いたいコンテキストを付け足しておく. 通常,Wolfram言語は新しいコンテキストを$ContextPathの始めに加える:
ここでMoleと入力すると,コンテキストPhysicalUnits`のシンボル,つまりモル数を表すためのシンボルが選択される:
簡略名だけで参照すると,通常,検索パスで先に現れるコンテキストにある同名のシンボルが選択される.このため,検索パスの後の方で現れるコンテキストに同名のシンボルがある場合や,現行のコンテキストに同盟のシンボルがある場合,これらのシンボルは隠されてしまう.隠されたシンボルを参照するには,コンテキストを含む完全名を指定する必要がある.
$ContextPathで既存のシンボルを隠してしまうような新しいシンボルを導入した場合,メッセージが出力される.また,ノートブックフロントエンドが赤く色付けすることで隠されたシンボルを警告する.
大域コンテキストGlobal`に簡略名Moleでシンボルを作る.入力すると,同じ簡略名Moleで別のシンボルがある旨が警告される:
単にMoleと参照すると,コンテキストパスに最初に出てくるシンボルPhysicalUnits`が選択されてしまう:
既存のシンボルを隠してしまうようなシンボルを一度導入してしまうと,$ContextPathを変更して検索パス指定のコンテキストの並び順を変えるか,シンボル自体を除去するまでは遮蔽効果が続いてしまう.除去するには単にシンボルの持つ値を消すだけでは不十分で,シンボル自体を消し去る必要がある.除去はRemove[s]を使い行う.
Clear[s]
シンボルの持つ値を消去する
Remove[s]
シンボル自体を除去する
シンボルの消去と除去
シンボルPhysicalUnits`Moleを除去する:
また,Moleを参照すると,今度はシンボルBiologicalOrganisms`Moleが選択される:
シンボル名が出力されるとき,Wolfram言語はその正式名と簡略名のどちらかを出力に使う.実際に出力される名前は,現行コンテキスト$Contextと検索パス$ContextPathの現行設定に対応して,該当シンボルを取得するために必要な名前である.
最初のシンボルは簡略名で表示される.指定するときも簡略名だけだと最初のシンボルが選択される:
簡略名を入力し,その名前に相当するシンボルがどのコンテキストにも存在しない場合は,それは新規のシンボルとして生成される.そのとき,新規シンボルは$Contextにある現行コンテキストにおいて作られる.
簡略名treeを入力すると,シンボルが新規に作られる:
現行コンテキストはGlobal`だから,シンボルtreeはそこにできる:
コンテキストとパッケージ
Wolfram言語で書かれたパッケージにはパッケージの外部で使うために設けられた各種のシンボルが入っている.
一般規約として,パッケージの読込み時に定義される新規のシンボルはすべて個別のコンテキスト,つまり,そのパッケージに関連付けられたコンテキストに入れられることになっている.パッケージが読み込まれる際は,適切なコンテキストが検索パス$ContextPathの先頭に付け加えられる.
素数証明のためのパッケージを読み込ませる:
検索パス$ContextPathの先頭にこのパッケージのコンテキストが付け足される:
シンボルProvablePrimeQはパッケージによって設定されたコンテキストに入っている:
検索パスにコンテキスト指定があるので,簡略名だけで参照できる:
パッケージにあるシンボルには非常に長い参照名を持つものが数多くある.しかし,それらの参照は,ほとんどの場合,簡略名だけで間に合う.パッケージが読み込まれると同時に,パッケージのコンテキストが$ContextPathに付け足されるからである.簡略名を入力すると,パスが自動検索されるため適切なコンテキストが判明する.
それでも問題が起らないとは限らない.2つのパッケージを使い,そのどちらにも同じ簡略名の変数があると競合が起ってしまう.実際にパッケージを読み込ませると,2つ目が読み込まれる際には警告が発せられ,新しいパッケージのシンボルにより先のパッケージのシンボルが隠蔽されてしまうという旨が表示される.
新たにパッケージを読み込ませる.すると,PrimalityProving`のコンテキストにあるシンボルProvablePrimeQが新しいシンボルで隠蔽されてしまう:
それでも,正式名を使えば参照することができる:
競合状態は何もパッケージ間だけで起るものではない.読み込まれたパッケージとユーザが現行セッションで直接入力したものとの間でも起り得る.現行コンテキストで何かシンボルを定義したとすると,読み込むパッケージに同名のシンボルがあると,後者が隠されてしまうことがある.理由は,検索パスのコンテキストが現行コンテキストより優先されるためである.
現行コンテキストに関数を1つ定義する:
この関数は複素数をスカラーとみなす:
現行コンテキストのScalarQ関数が,パッケージの関数により隠されてしまう:
パッケージのScalarQが使われる:
シンボルの隠蔽問題が起ったら,まず,Remove[s]を使い必要でなくなったシンボルを除去する.それでも問題が解消しないときは,検索パス$ContextPathや現行コンテキスト$Contextを再編集し,必要なシンボルを含むコンテキストが先に検索されるようにする.
$Packages
現行Wolfram言語セッションに読み込まれている全パッケージのコンテキストがリスト形式で登録してある
パッケージのコンテキスト
Wolfram言語パッケージ
Wolfram言語の最も重要な特徴のひとつに拡張性が非常に高いということがある.数学関数や他の標準的な機能が組み込まれてはいるが,Wolfram言語を使うことで,機能性をさらに向上することが可能になっている.
ほとんどの計算は標準版Wolfram言語の持つ組込み関数で十分間に合う.しかし特殊な分野の計算は組み込まれていない関数を必要とする場合がある.
そのようなとき,必要な関数がパッケージに入っているかもしれない.パッケージはWolfram言語で書かれたプログラムファイルであり,Wolfram言語に特定の応用分野について「教授する」定義の集まりから構成されている.
<<package
Wolfram言語パッケージを読み込む
Wolfram言語パッケージの読込み
パッケージに入っている関数を使うには,まず,パッケージをWolfram言語に読み込ませる必要がある.やり方の詳細に関しては「外部プログラム」を参照してほしい.パッケージを参照する際に必要となる名前の指定に関する約束事が説明してある.
Wolfram言語パッケージを読み込ませる:
関数ProvablePrimeQは,このパッケージで定義されている:
パッケージ間での関数名の衝突のような問題に関連した微妙なことが多数ある.これは「コンテキストとパッケージ」で詳しく触れる.ここで言及しておきたいのは,まだ読み込まれていないパッケージの中にある関数を参照してはならないということである.誤って参照してしまうと,Wolfram言語は重複した名前についての警告メッセージを表示し,最後に定義したものを使う.つまり,自分が使いたい関数が使われないということである.パッケージの関数を使うのである.このようなときは,Remove["name"]を実行すると,パッケージの関数を除去することができる.
Remove["name"]
誤って定義した関数を除去
競合している関数の除去
パッケージを追加することでWolfram言語の機能を拡張できるということは,裏を返せばどこまでが「Wolfram言語本来の部分」か,というような境界ができないことを示している.実際には,パッケージの関数と組込み関数の間には全く違いがない.
Wolfram言語の中核に組み込まれている関数の多くは,実際にはWolfram言語パッケージとして実装されている.それでも,一部のWolframシステムを除いて,これらのパッケージは先読みされるので,関数は常に使える状態にある.
Wolfram言語本来の部分をさらに不明確にするものとして,次の機能がある.「パッケージの自動読込み」でやり方を説明するが,パッケージにある関数を参照するたびに関数の定義がパッケージから自動的に読み込まれるようにすることができる.関数が参照されなければ,関数は存在しないままだが,一度参照されると,その定義はパッケージから自動的に読み込まれる.
便宜上,Wolfram言語本来の部分とは,すべてのWolframシステムに共通な関数からなる部分ととらえればよいだろう.ここでは,これらの関数を中心に解説していくことにする.
それでも,ほとんどのWolframシステムのバージョンには標準でWolfram言語パッケージが添付されているため,より多くの関数が定義済みになっている.それらの関数を使うには,パッケージを手動で読み込ませる必要がある.
Wolfram言語標準パッケージの情報はドキュメントセンターで得ることができる:

19.gif

適当なWolframシステムを設定することで,このようなパッケージを先読みさせたり,必要なときに自動的に読み込ませることも可能である.そうすると,組込み関数と同様に扱える関数が多くなるが,Wolfram言語のレファレンスページではこのような関数については説明しない.
最後に,パッケージとノートブックの関係について触れておく.これらはともに使用中のコンピュータシステムにファイルとして保存され,またWolframシステムに読み込ませることができる.両者の違いは,ノートブック文書は表示される(ノートブックフロントエンドを使って)ためにあるのに対して,パッケージはWolfram言語の入力のためにある,ということである.それでも,実際,多くのノートブックはパッケージとみなされる部分を含み,それらはWolfram言語の入力として使われる一連の定義を持っている.また,ノートブックの自動保存に対応するパッケージの設定もある.
パッケージ
代表的なWolfram言語パッケージにおいて新規に生成されるシンボルは2種類ある.そのひとつは,パッケージ外部への送出(エキスポートと呼ぶ)に使われるシンボルで,もうひとつは,パッケージ内部だけで使われるシンボルである.2つを区別するには別々のコンテキストを指定する必要がある.
デフォルトで,外部送出用のシンボルは,Package`という名前のコンテキストに入れられる.パッケージの読込み時にこのコンテキストが自動的に検索パスに付け加えられ,それを参照するには簡略名だけでよくなるようになっている.
また,内部処理だけで使うシンボルはプライベートなコンテキスト Package`Private`に導入される.このコンテキストは検索パスには追加されない.このため,シンボルの参照には正式名を使う必要がある.
Package`
外部送出用パッケージのシンボルを導入するコンテキスト
Package`Private`
内部処理用パッケージのシンボルを導入するコンテキスト
System`
組込みシンボルのあるコンテキスト
Needed1`
,
Needed2`
,
パッケージで必要な他のコンテキスト
パッケージに関連したコンテキスト
パッケージからコンテキストを設定するための命令書式および手順がある.それらを使い,現行コンテキスト$Contextと検索パス$ContextPathを適切に設定することで,新規シンボルを必要なコンテキストに導入できる.
BeginPackage["Package`"]
パッケージ名 Package` を現行コンテキストにし,検索パスにはシステムコンテキストSystem`だけを指定する
f::usage="text"
,
外部送出用オブジェクトを作成する
Begin["`Private`"]
現行コンテキストを Package`Private`内だけで有効なものにする
f[args]=value
,
パッケージの定義式本体を記述する
End[]
定義記述を終えて,コンテキストを Package`に戻す
EndPackage[]
パッケージコンテキスト Package`を検索パスの先頭に追加してパッケージを終了する
パッケージにおけるコンテキスト設定の標準手続き
BeginPackage["Collatz`"]

Collatz::usage =
"Collatz[n] gives a list of the iterates in the 3n+1 problem,
starting from n. The conjecture is that this sequence always
terminates."

Begin["`Private`"]

Collatz[1] := {1}

Collatz[n_Integer] := Prepend[Collatz[3 n + 1], n] /; OddQ[n] && n > 0

Collatz[n_Integer] := Prepend[Collatz[n/2], n] /; EvenQ[n] && n > 0

End[ ]

EndPackage[ ]
The sample package Collatz.m.
パッケージの最初の部分でusageメッセージを定義するのが,エキスポートしたい記号が適切なコンテキストで作られていることを確実にする一般的な方法である.このメッセージを定義することで,そこで挙げた記号のみがエキスポートしたい記号となる.この記号はその時点で現行の Package`で作られる.
パッケージでは通常数多くの関数定義を行い,そのためパラメータや一時変数等の各種シンボルを導入しておく必要がある.これらのシンボルはデフォルトでパッケージのプライベートコンテキスト Package`Private`に入れておくことになっている.なお,パッケージ読込みの際は,プライベートコンテキストは検索パスへ追加されない.
上記例のパッケージを読み込ませる:
パッケージにあるコマンドEndPackageが実行される時点でパッケージのコンテキストが検索パスに追加される:
関数CollatzはコンテキストCollatz`にあることが分かる:
パッケージのプライベートコンテキストCollatz`Private`に何があるか参照してみる.nの名前の引数があることが分かる:
Collatzのパッケージでは,定義する関数はすべて組込み関数に依存するだけである.しかし,場合によっては,他のパッケージにある関数を呼び出すものを作らなければいけないときもある.
そのときは,2つのステップを踏む必要がある.その第1ステップでは,必要な関数の存在する別のパッケージを読み込ませる.そして,第2ステップで,関数の定義されているコンテキストを検索パスに追加する.
現行セッションのどこでも,<<context`の命令書式を使い必要なパッケージを読み込ませることが可能である.(パッケージファイルにアクセスする上でシステム非依存のコンテキスト名ををシステムに依存したファイル名に変換する必要がある.詳しくは「パッケージのファイル」を参照のこと.)ただし,必要なときだけ自動的にパッケージが読み込まれるようになるとより便利である.Needs["context`"]と呼ばれる機能が提供されているので,それを使い必要なコンテキストを指定しておく.すると,そのコンテキストが現行パッケージのリスト$Packagesになければ,パッケージが自動的に読み込まれる.
Get["context`"]
または
<<context`
コンテキストに対応したパッケージを読み込む
Needs["context`"]
コンテキストが現行パッケージリスト$Packagesになければ対応したパッケージを読み込む
BeginPackage["Package`",{"Needed1`", }]
システムコンテキストSystem`の他にコンテキストを検索パスに指定する
パッケージの読込み用の関数
BeginPackage["Package`"]を使うとき,パッケージ名の引数だけを与えると,組込みシンボル用のコンテキストの他には,Package`のコンテキストしか検索パスに追加されない.もし,ユーザの作成するパッケージに別のパッケージの関数に依存する定義式があると,そのパッケージのコンテキストも検索パスに加えておかなければいけない.それをするには,BeginPackageの命令に第2の引数として必要なコンテキスト名をリスト形式で列記する.すると,BeginPackageNeedsの機能を自動的に使いコンテキストの作成に必要なパッケージを読み込み,検索パスに必要なコンテキストを加える仕組みになっている.
Begin["context`"]
現行コンテキストを変更する
End[]
前のコンテキストに戻す
コンテキストを操作する関数
Beginのようなコンテキスト操作の命令を実行すると,ユーザの入力するシンボル名の解釈が変わる.ただし,変更は命令の後に続く式から有効になる.Wolfram言語では,式は一括で読み込まれるので,式の部分評価が始まる前に,式にあるシンボルの参照名がすべて解釈されることになっている.このため,式にBegin命令があっても,命令が実行される前に式の参照名が先に解釈されてしまう.つまり,Begin命令を使ってもその場ではコンテキスト変更の効果は得ることができない.
このようにコンテキストの操作命令は次の式が読み込まれるまで効力を発揮しないので,パッケージで使う際は,命令文だけを単体で別行に入力することが必要である.
式の評価が始まる前に,参照名xが解釈される.したがって,Beginは何の効果ももたらさない:
コンテキストの操作命令は主にパッケージの読込みで使うものである.ただし,場合によっては計算を進める上で対話的に使うと便利なときもある.
パッケージにある関数を実行する際は,TraceDialogを使うと対話モードでコンテキスト命令が使える.関数の使う引数や一時変数は,通常,パッケージのプライベートコンテキストにある.このコンテキストは検索パスには指定されてないので,引数や変数は正式名で表示される.また,それらを参照するには正式名を使う必要がある.そこで,ダイアログを設け,Begin["Package`Private`"]の命令を実行すればパッケージのプライベートコンテキストを現行のものにできる.そして,引数等の表示では簡略名が使われるようになり,参照するにも簡略名だけでよくなる.
パッケージのファイル
Wolfram言語パッケージを作ったり使ったりするとき,ファイルをシステムに依存しない方法で参照することが望ましい.コンテキストを利用するとそうすることができる.
基本的な考え方は,コンピュータシステムのそれぞれにWolfram言語コンテキストの名前に対応するファイル名の約束がある.したがって,コンテキストを使ってファイルを参照すると,使っているWolfram言語のバージョンがコンテキスト名をコンピュータシステムに合わせたファイル名に変換する.
<<context`
コンテキスト名を指定してのファイルの読込み
ファイルをコンテキストで指定
Wolframシステムに付属している標準パッケージの読込み:
name.mx
DumpSave形式のファイル
name.mx/$SystemID/name.mx
ユーザのコンピュータシステムにおけるDumpSave形式のファイル
name.m
Wolfram言語のソース形式のファイル
name/init.m
指定したディレクトリの初期化ファイル
dir/
$Pathに指定する別のディレクトリのファイル
<<name`で検索される代表的なパス
Wolfram言語では<<name`でファイルの適切なバージョンを読み込む.まず,使っているコンピュータシステムに最適化されている name.mxという名前を持つファイルを使うことを試み,それが見付からないときは,通常のシステムに依存しないWolfram言語入力が書かれた name.mの形のファイルを読み込む.
name がディレクトリのとき,Wolfram言語はそのディレクトリにある初期化ファイルinit.mを読む.init.mファイルの目的は,たくさんの別々のファイルからなるWolfram言語パッケージの設定を行う便利な方法を提供することである.コマンド<<name`を入力すると,init.mが読み込まれてパッケージ全体の初期化が行われ,必要なファイルがすべて読み込まれる.
パッケージの自動読込み
他のチュートリアルでは<<package およびNeeds[package]を使ってWolfram言語パッケージを明示的にロードする方法を説明した.しかし,ある特定のパッケージが必要なときに自動的にそれがロードされるようにWolfram言語を設定しておいた方がよい場合もある.
パッケージを自動で読み込み,パッケージに定義されているシンボルを参照するには,DeclarePackageと呼ばれるパッケージを宣言する機能が使える.参照したいシンボルを宣言しておくと,実際に参照するときに必要なパッケージが自動的に読み込まれる.
DeclarePackage["context`",{"name1","name2",}]
シンボル名 namei が参照されると,コンテキストのパッケージを自動的に読み込む
パッケージの自動読込み
シンボルVariationalDEulerEquationsFirstIntegralVariationalMethods`のパッケージに対応付けておく:
VariationalDを参照すると,パッケージが自動的に読み込まれる:
読み込ませたいパッケージがたくさんあるときは,必要なDeclarePackageの宣言文を盛り込んだ「参照名ファイル」を別途用意しておき,どのシンボルの参照があったらどのパッケージを読み込むか指定しておくと便利である.そうすれば,計算セッションを始める際に参照名ファイルだけを読み込むだけで自動読込みの準備が完了する.
関数DeclarePackageの働き方として,宣言時にすぐ指定シンボルが生成され,Stub(スタブ)と呼ばれる特殊な属性が同シンボルに付加される.そして,実際の計算セッションで,宣言シンボルを参照すると,Stub属性により対応パッケージを自動的に読み込むように判断される.
シンボルとコンテキストの名前による操作
Symbol["name"]
名前でシンボルを作成する
SymbolName[symb]
シンボルの参照名を検索する
シンボルの作成と検索
シンボルxを作る:
参照名は文字列として定義されている:
xのシンボルをまた作る:
x=2のようにxに一度値を割り当てたら,計算ではxが現れるたびに値2に置換される.しかし,場合によっては,置換させずにもとの名前で参照し続けたいときがある.
そうするにはxに参照名を与えておく.シンボルxの文字列による名前を"x"としておけば,xに実際に値が置換されても,文字列"x"で引き続きxを参照できるようになる.
シンボルxxpの名前を"x""xp"にする:
xに数値を設定する:
xの入力は2に置き換えられる:
だが,文字列による名前"x"はそのままである:
NameQ["form"]
文字列 form にマッチする名前のシンボルがあるかどうかを判定する
Names["form"]
文字列 form にマッチする名前を持つシンボルをすべて列挙する
Contexts["form`"]
文字列 form にマッチする名前を持つコンテキストを列挙する
文字列名を使ったシンボルとコンテキストの参照
xxpは本セッションで作ったシンボルだが,xppはそうでない:
「文字列パターン」で説明する文字列パターンを使いシンボルの検索や指定を行うことができる.例えば,"x*"と文字列を入力すると,xで始まるすべての名前を表せる.
現行セッションで作ったxで始まるすべてのシンボル名を列挙する:
この名前パターンを使うと,組込み関数が検索できる:
スペルがWeierstrssPに近い名前を検索する:
Clear["form"]
文字列 form にマッチする参照名を持つすべてのシンボルの値を消去する
Clear["context`*"]
コンテキストにあるすべてのシンボルの値を消去する
Remove["form"]
文字列 form にマッチする参照名を持つすべてのシンボルを完全に除去する
Remove["context`*"]
コンテキストにあるすべてのシンボルを完全に除去する
参照名とコンテキスト指定によるシンボルの消去と除去
xで始まる名前を持つすべてのシンボルの値を消去する:
それでも,"x"はまだ既知である:
しかし,xの値は消去してある:
今度は,xで始まる名前を持つすべてのシンボルを除去させる:
これで,"x"による名前も未知になった:
Remove["Global`*"]
大域コンテキストGlobal`にあるシンボルすべてを完全に除去する
ユーザ定義の全シンボル除去
特にコンテキスト指定をしていなければ,ユーザの導入するシンボルは大域コンテキストGlobal`に設けられる.Remove["Global`*"]と入力すれば,作成したすべてのシンボルが一括除去できる.組込み関数はシステムコンテキストSystem`にあるから除去されることはない.
シンボル生成処理の内容確認
未知な名前を入力するとシンボルが新規に生成される.場合によっては,生成処理がどう進んだか確認しておきたい.方法がいくつか用意されているので例を挙げながら見てみよう.
On[General::newsym]
シンボルを新規に生成する際にその旨を表示し,内容を確認できるようにする
Off[General::newsym]
シンボルが新規に生成する際にメッセージ表示を停止する
新規シンボル生成時の内容確認
シンボル生成内容の確認をオンにする:
生成されたそれぞれのシンボルについての確認情報が表示される:
確認情報表示をオフに戻す:
内容が確認できれば,タイプミス等の誤りを見付けるのにも便利だろう.Wolfram言語自体は入力されたものがタイプミスかどうか判別できない.生成内容を表示させるようにしておけば,少なくともユーザ自身で入力の正確性を確認できる.
$NewSymbol
新規にシンボルを生成するたびに実行する,シンボルの参照名とコンテキスト名を引数とした関数を指定する
シンボル生成時適用の関数指定
新しくシンボルを作成するときは,単にシンボル内容を表示させるだけでなく,特別な処理を行いたいときもあるだろう.そのようなときは,大域変数$NewSymbolを使い,それに処理を施す関数を割り当てておくと,新規のシンボルが生成されるたびにシンボルの参照名とコンテキスト名の文字列が関数の引数として自動的に適用されるようになる.
新規に作るたびにシンボルに適用させる関数を定義しておく:
vwが新たに作成され,両方に上記の関数が適用される: