建立 Mathematica 程序包

在一个典型的 Mathematica 程序包中,一般引入两种类型的新符号,一种是输出为外部程序包使用的符号,另一种仅在本程序包中使用的符号. 可以将这两种类型的符号放入不同的上下文以便区分.

通常的约定是将用作输出的符号放在名为 的上下文内,这与程序包的名称相对应. 当这个程序包读入时,它将这个上下文加到上下文搜索路径中去,所以在这个上下文中的符号可以通过短名调用.

仅在程序包内使用的符号习惯上放在名为 的上下文内. 这个上下文没有加入到上下文的搜索路径中去. 于是,这些符号只有通过全名才能调用.

Package`用于输出的符号
Package`Private`仅在内部使用的符号
System`Mathematica 中的内部符号
Needed1`, Needed2`, ...在程序包中需要的其它上下文

Mathematica 程序包中使用上下文的约定.

有一个标准的 Mathematica 指令序列用来设置程序包中的上下文. 这些指令设置 $Context$ContextPath 的值以便新引入的符号放在适当的上下文之中.

BeginPackage["Package`"] 作为当前上下文,仅将 放在上下文搜索路径中
f::usage="text", ...引入作为输出的目标
Begin["`Private`"]设置当前上下文为
f[args]=value, ...给出在程序包中定义的主体
End[]转换到前一个上下文(这里为
EndPackage[]上下文结束程序包,将 放到上下文搜索路径前面

在程序包中的上下文控制指令标准序列.

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 程序包.

定义在一个程序包开头使用 信息的约定是在合适的上下文中产生用作输出的符号的一个基本的技巧. 在定义这些信息时,所涉及的符号都是用作输出的符号,这些符号都在作为当前上下文的 中产生.

在一个程序包中函数的实际定义中,有许多引入参数、局部变量等新符号. 约定将这些符号放在 上下文中,当程序包读入后它不放在上下文的搜索路径之中.

这里读入前面的样本程序包.
In[1]:=
Click for copyable input
在这个包中的 EndPackage 指令将与该包对应的上下文放入上下文搜索路径中.
In[2]:=
Click for copyable input
Out[2]=
函数在 上下文中产生.
In[3]:=
Click for copyable input
Out[3]=
参数 放在专用上下文 中.

包中所定义的函数仅依赖于 Mathematica 的内部函数,但通常在一个包中定义的函数依赖着另一个包中定义的函数.

为此必须有两个条件,第一是读入另一个程序包以便所需的函数有定义,第二是上下文搜索路径必须包括这些函数所在的上下文.

可以明确告诉 Mathematica 在任一处读入程序包,使用的指令为 . ("程序包中的文件" 讨论了从与系统不相关的上下文名称到与系统相关的文件名之间的转换). 然后,设置为需要时就读入某一程序包. 指令 Needs["context`"] 告诉 Mathematica 当与程序包相关的上下文不在 $Packages 列表中时就读入这个程序包.

Get["context`"] <<context`读入特定上下文对应的程序包
Needs["context`"]当指定的上下文不在 $Packages 中时读入程序包
BeginPackage["Package`",{"Needed1`", ... }]
开始一个包,指定除 外所需要的上下文

指定独立包函数.

当使用一个具有一个变量的 BeginPackage["Package`"] 时,Mathematica 仅将 上下文和 Mathematica 内部符号上下文放在上下文的搜索路径之中. 在自定义包中涉及到其它包中的函数时,一定要确认这些包含在上下文的搜索路径之中,这可以在 BeginPackage 的第二个变量中给出另外的上下文列表即可. BeginPackage 就自动调用 Needs,必要时读入与这些上下文对应的程序包,确定这些上下文在上下文的搜索路径之中.

Begin["context`"]转向一个新的当前上下文
End[]转向前一个上下文

Context 操作函数.

Begin 等上下文操作函数的执行改变了 Mathematica 翻译所输入名字的方式. 但要意识到这种改变仅对输入的下一个表达式有效,其原因是 Mathematica 总是先读入一个完整的表达式,在执行表达式的任何项之前翻译它中的名字. 于是,当一个特定的表达式中执行 Begin 时,表达式中的名称已被翻译,使 Begin 无法再产生效果.

上下文操作函数对第2个读入的完整表达式不产生影响这一事实意味着当编写 Mathematica 程序包时必须作为分离的表达式给出这些函数,经常是在不同的行.

的名字在表达式执行之前已经翻译,所以 Begin 没有作用.
In[5]:=
Click for copyable input
Out[5]=

上下文操作函数首先用作程序包的一部分被 Mathematica 读入. 有时,交互式地应用它们也很方便.

例如,在执行一个包中定义的函数时用 TraceDialog 进行一个对话,函数中的参数和临时变量一般是在与这个有关的上下文中. 由于这个上下文不在上下文的搜索路径之中,Mathematica 将显示这些符号的全名,并且需要用户输入全名去调用这些变量. 但还可以用 Begin["Package`Private`"] 使包专用上下文成为当前上下文. 这就使 Mathematica 显示符号的短名,也就可以用短名调用这些符号.

New to Mathematica? Find your learning path »
Have a question? Ask support »