在mathematica包中定义私有函数

时间:2011-02-27 19:57:47

标签: package wolfram-mathematica private-functions

我不确定我是如何正确定义私人功能的。 当我写一个包mathematica时,我就是这样做的:

BeginPackage["myPackage`"]
myPublicFunction::usage="myPublicFunction blahblahblah";
Begin["Private"]
myPrivateFunction[input_]:= ... ;
myPublicFunction[input_]:= ... ;
End[]
EndPackage[]

这是正确的方式还是我错过了什么?

1 个答案:

答案 0 :(得分:12)

是的,这是正确的方法。理解一些内部包函数可能会有所回报。 Mathematica上下文与其他语言中的名称空间类似。它们可以嵌套。每个符号都属于某种语境。在任何特定时刻,某些情境都是“当前的”。每当创建新符号时,系统必须决定符号将属于哪个上下文。这发生在分析时。这里的基本数量(变量)是$ContextPath。它基本上是符号的搜索路径。它是一个上下文列表,每当系统看到一个新符号时,它会测试{{1}上某个上下文中是否存在具有相同短名称的符号(即符号名称正确,没有上下文) }}。如果它确实存在,那么符号的给定出现将与现有符号相关联。如果没有,则在当前上下文中创建符号。请注意,这是一个动态的事情 - 如果您随时更改$ContextPath,则下一个符号出现可以与不同的符号相关联。

无论如何,$ContextPath所做的就是它只用BeginPackage替换$ ContextPath的当前值,加上可能通过{youPublicPackageContext, "System'"}的第二个可选参数公开导入的其他上下文。因此,如果“公共”部分中的所有符号不在“系统”或您导入的其他上下文中,则会将其解析为公共上下文。而BeginPackage所做的是将EndPackage的值恢复为开始加载包之前的值。因此,从技术上讲,使用消息并不是在主要上下文中使符号公开的唯一方法 - 您也可以简单地用分号键入一个符号,例如$ContextPath(这种做法不鼓励,我只是提到它澄清机制)。现在,当您输入myFunction;时会发生的情况是当前上下文变为Begin["'Private'"](子上下文)。 YourContext'Private'未更改。因此,在那里输入的任何符号(在您的公共包或其他导入的包中不存在(即当前在$ContextPath上的上下文))会自动解析为$ContextPath子上下文。

真正使这些符号成为私有的是,无论何时将包导入其他上下文(包),只有主包被添加到'Private',而不是其子包。从技术上讲,您可以通过手动将$ContextPath添加到$ ContextPath(例如,YourPackage'Private')来中断封装,然后所有私有函数和其他符号将在您执行导入的特定上下文中变为公共。同样,这种做法不鼓励,但它解释了机制。最重要的是,当我们知道如何解析符号时,可以完全理解私有或公共的概念,以及PrependTo[$ContextPath, YourPackage'Private']$ContextPath(另一个系统变量给出当前值)的操作是什么上下文),由$ContextBegin等命令执行。换句话说,原则上可以使用用户定义的代码模拟BeginPackageBeginPackageBeginEnd的操作。这里只有一些原则(我试图在上面概述),并且机制本身实际上非常暴露给用户,因此,如果在某些罕见的情况下,人们可能想要一些其他行为,那么可以制作使用EndPackage$ContextPath进行一些“自定义”操作,以确保一些非标准的符号解析方式,从而以某种“非标准”方式控制包级规模的封装。我并不鼓励这样做,只是提一下要强调的是,这种机制实际上比表面看起来更简单,更可控。