我或多或少有以下设置。在~/path/to/my/packages
我有两个包package1.m
和package2.m
。例如,每个包的大纲如下:
BeginPackage["package1`"]
Unprotect@@Names["package1`*"];
ClearAll@@Names["package1`*"];
Begin["`Private`"]
vecNorm[vec_?VectorQ]:=Module[{},Return[Sqrt[vec.vec]]];
End[]
Protect@@Names["package1`*"];
EndPackage[]
现在,我的问题是我想使用vecNorm
package1.m
中定义的package2.m
。如何在package1
内加载({安全地)package2
?
目前,我按如下方式手动加载两个包:
SetDirectory[StringJoin[NotebookDirectory[], "packages"]];
Needs["package1`"]
Needs["package2`"]
保存在~/path/to/my
中的笔记本中。我想手动加载 {/ em> package2
,而后者将自动加载package1
。一般来说,我想要一个尽可能少地改变mathematica路径等的解决方案。什么应该是实现这一目标的最佳做法?
PS :安全地我的意思是,将来,当我定义package3
时将使用vecNorm
并将加载package1
同样也不会发生冲突。
答案 0 :(得分:14)
有两种通常推荐的加载包的方法。一个是所谓的公共导入,在你的设置中它将作为
完成BeginPackage["package2`",{"package1`"}]
(* Usage messages etc *)
Begin["`Private`"]
(* code here *)
End[]
EndPackage[]
在此处,您在列表中指明要加载的包的上下文名称,该列表是BeginPackage
的第二个可选参数。这种导入方式称为public,因为加载的包将在加载主包后保留在$ContextPath
上,因此可以公开使用。
第二种方法称为私有导入,并以
示意性地完成BeginPackage["package2`"]
(* Usage messages etc *)
Begin["`Private`"]
Needs["package1`"]
(* code here *)
End[]
EndPackage[]
在此方法中,加载的第二个包只能用于加载它的包(带Needs
),因此是私有导入。
您需要哪种方式取决于具体情况。除非我必须将它们公开,否则我会尝试将所有导入设为私有。但是,对于调试,首先进行公共导入可能很方便,因为那时你可以直接在顶层玩第二个包。
至于安全性,您可以通过任意数量的包装入包装,这将是安全的。当您同时将多个包加载到同一个上下文中时,只要这些包没有具有相同短名称的公共符号,这将是安全的。否则,您将遇到所谓的阴影问题,但最好尽一切努力避免这种情况(总是可能的)。