|
2.7.10 パッケージ
代表的な Mathematicaパッケージにおいて新規に生成されるシンボルは2種類ある.その1つは,パッケージ外部への送出(エキスポートと呼ぶ)に使われるシンボルで,もう1つは,パッケージ内部だけで使われるシンボルである.2つを区別するには別々のコンテキストを指定する必要がある.
デフォルトで,外部送出用のシンボルは,パッケージから取った名前のコンテキストに入れられる.パッケージの読込み時にこのコンテキストが自動的に検索パスに付け加えられ,それを参照するには簡略名だけでよくなるようになっている.
また,内部処理だけで使うシンボルはプライベートなコンテキスト`Private`に導入される.このコンテキストは検索パスには追加されない.このため,シンボルの参照には正式名を使う必要がある.

パッケージに関連したコンテキスト
パッケージからコンテキストを設定するための命令書式および手順がある.それらを使い,現行コンテキスト $Contextと検索パス $ContextPathを適切に設定することで,新規シンボルを必要なコンテキストに導入できる.

パッケージにおけるコンテキスト設定の標準手続き
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[ ]
パッケージ例 Collatz.m
パッケージの最初の部分でusageメッセージを定義するのが,エキスポートしたい記号が適切なコンテキストで作られていることを確実にする一般的な方法である.このメッセージを定義することで,そこで挙げた記号のみがエキスポートしたい記号となる.この記号はその時点で現行のPackage`で作られる.
パッケージでは通常数多くの関数定義を行い,そのためパラメータや一時変数等の各種シンボルを導入しておく必要がある.これらのシンボルはデフォルトでパッケージのプライベートコンテキストPackage`Private`に入れておくことになっている.なお,パッケージ読込みの際は,プライベートコンテキストは検索パスへ追加されない.
上記例のパッケージを読み込ませる.
In[1]:= <<Collatz.m
パッケージにあるコマンド EndPackageが実行される時点でパッケージのコンテキストが検索パスに追加される.
In[2]:= $ContextPath
Out[2]= 
関数 Collatzはコンテキスト Collatz`にあることが分かる.
In[3]:= Context[Collatz]
Out[3]= 
パッケージのプライベートコンテキストCollatz`Private`に何があるか参照してみる. nの名前の引数があることが分かる.
In[4]:= ?Collatz`Private`*

Collatzのパッケージでは,定義する関数はすべて組込み関数に依存するだけである.しかし,場合によっては,他のパッケージにある関数を呼び出すものを作らなければいけないときもある.
そのときは,2つのステップを踏む必要がある.その第1ステップでは,必要な関数の存在する別のパッケージを読み込ませる.そして,第2ステップで,関数の定義されているコンテキストを検索パスに追加する.
現行セッションのどこでも, <<context`の命令書式を使い必要なパッケージを読み込ませることが可能である.(パッケージファイルにアクセスする上で Mathematicaコンテキスト名をシステムに依存した ファイル名に変換する必要がある.詳しくは 2.12.5を参照のこと.)ただし,必要なときだけ自動的に パッケージが読み込まれるようになるとより便利である.Needs["context`"]と呼ばれる機能が提供されているので,それを使い必要なコンテキストを指定しておく.すると,そのコンテキストが現行パッ ケージのリスト $Packagesになければ,パッケージが自動的に読み込まれる.

パッケージの読込み用の関数
BeginPackage["Package`"]を使うとき,パッケージ名の引数だけを与えると,組込みシンボル用のコンテキストの他には,指定パッケージ名のコンテキストしか検索パスに追加されない.もし,ユーザの作成するパッケージに別のパッケージの関数に依存する定義式があると,そのパッケージのコンテキストも検索パスに加えておかなければいけない.それをするには, BeginPackageの命令に第2の引数として必要なコンテキスト名をリスト形式で列記する.すると, Needsの機能が自動的に使われコンテキストの作成に必要なパッケージが読み込まれ,検索パスには必要なコンテキストが加えられる仕組みになっている.

コンテキストを操作する関数
Beginのようなコンテキスト操作の命令を実行すると,ユーザの入力するシンボル名の解釈が変わる.ただし,変更は命令の後に続く式から有効になる. Mathematicaでは,式は一括で読み込まれるので,式の部分評価が始まる前に,式にあるシンボルの参照名がすべて解釈されることになっている.このため,式に Begin命令があっても,命令が実行される前に式の参照名が先に解釈されてしまう.つまり, Begin命令を使ってもその場ではコンテキスト変更の効果は得ることができない.
このようにコンテキストの操作命令は次の式が読み込まれるまで効力を発揮しないので,パッケージで使う際は,命令文だけを単体で別行に入力することが必要である.
式の評価が始まる前に,参照名 xが解釈される.したがって, Beginは何の効果ももたらさない.
In[5]:= Begin["a`"]; Print[Context[x]]; End[ ]

Out[5]= 
コンテキストの操作命令は主にパッケージの読込みで使うものである.ただし,場合によっては計算を進める上で対話的に使うと便利なときもある.
パッケージにある関数を実行する際は, TraceDialogを使うと対話モードでコンテキスト命令が使える.関数の使う引数や一時変数は,通常,パッケージのプライベートコンテキストにある.このコンテキストは検索パスには指定されてないので,引数や変数は正式名で表示される.また,それらを参照するには正式名を使う必要がある.そこで,ダイアログを設け, Begin["Package`Private`"]の命令を実行すればパッケージのプライベートコンテキストを現行のものにできる.そして,引数等の表示では簡略名が使われるようになり,参照するにも簡略名だけで良くなる.
|