pha*_*234 5 wolfram-mathematica
我有以下情况:
On[t::shdw]
Message[t::shdw,"t","Foobar","Dork"]
-> t::shdw: Symbol t appears in multiple contexts Foobar; definitions in context Dork may shadow or be shadowed by other definitions. >>
Off[t::shdw]
Message[t::shdw,"t","Foobar","Dork"]
-> **No Warning**
<<MASStoolbox`
-> t::shdw: Symbol t appears in multiple contexts {MASStoolbox`MASS`,Global`}; definitions in context MASStoolbox`MASS` may shadow or be shadowed by other definitions. >>
Run Code Online (Sandbox Code Playgroud)
怎么可能?是否On
和Off
加载软件包时只影响当前笔记本电脑并没有任何影响?如果是这样,怎么能摆脱像这样的消息呢?如何处理阴影错误?
您观察到的原因是该语句Off[t::shdw]
禁用了t
当前在其他程序包加载期间创建的符号的阴影消息$ContextPath
,而不是另一个符号的阴影消息t
.t
如果您不想看到它,则应该禁用该秒的阴影消息.这是一个例子:
In[1]:= Off[Test1`a::shdw]
In[2]:=
BeginPackage["Test`"]
a
EndPackage[]
Out[2]= Test`
Out[3]= a
In[5]:= BeginPackage["Test1`"]
a
EndPackage[]
Out[5]= Test1`
Out[6]= a
Run Code Online (Sandbox Code Playgroud)
这里没有生成任何消息.
但是,一般情况下,我不想禁用阴影消息,因为阴影是一个严重的问题.阴影只是意味着符号搜索路径($ContextPath
)上当前有多个上下文,包含具有相同(短)名称的符号.基本上,如果符号被遮蔽,并且您通过其短名称(即没有包含包的符号)引用它,则无法保证实际使用具有相同短名称的几个符号中的哪一个.因此,正确处理这种情况的方法是完全避免阴影,这总是可能的,如果不总是方便的话.
避免阴影的最简单方法是将所需的包加载到包的私有部分,该部分从该行开始Begin["`Private`"]
.你Needs[your-package]
一如既往地打电话来做到这一点.这样,加载的包的上下文不会$ContextPath
与包的上下文一起保留.最糟糕的情况是,您需要加载两个包含冲突符号的包.一种方法是为其中一个构造一个包装器包,它将私下加载它并重命名冲突的符号.这可能不方便,因为您必须重命名包中的所有函数,即使那些不冲突的函数也是如此.以下是更灵活的变体示例:
第一包:
BeginPackage["Test`"];
g[x_?NumericQ] := x^2;
EndPackage[];
Run Code Online (Sandbox Code Playgroud)
第二包:
BeginPackage["Test1`"];
g[x_?NumericQ] := x^3;
EndPackage[]
Run Code Online (Sandbox Code Playgroud)
主要包装:
BeginPackage["Main`"];
f::usage = "A test function of a single argument";
Begin["`Private`"];
Block[{$ContextPath = $ContextPath},
Needs["Test`"];
(* Define first delegate private function *)
g1 = Symbol["g"]];
Block[{$ContextPath = $ContextPath},
Needs["Test1`"];
(* Define second delegate private function *)
g2 = Symbol["g"];
];
f[x_] := g1[x]*g2[x]
End[]
EndPackage[]
Run Code Online (Sandbox Code Playgroud)
现在,只要系统知道在哪里找到你的包:
In[2]:= Needs["Main`"]
In[3]:= f[x]
Out[3]= Test`g[x] Test1`g[x]
In[4]:= f[2]
Out[4]= 32
Run Code Online (Sandbox Code Playgroud)
我们对同一个公共函数使用了两个冲突的符号.使用Block
上面的方法来本地化使用第一个或第二个定义的代码g
.请注意,此方法存在一些不便之处,因为我们需要使用Symbol["your-symbol-name"]
,将解析延迟到运行时.
一个更简单的方法是用长名称来引用符号.在上面,我们可以使用Test`g
,Test1`g
然后不需要重型机械.然而,这有点不太灵活,因为您必须将符号的上下文"硬编码"到代码中.