Wolfram mathematica 如何全局关闭隐藏消息(symbol::shdw)?或任何其他';良好做法';建议?

Wolfram mathematica 如何全局关闭隐藏消息(symbol::shdw)?或任何其他';良好做法';建议?,wolfram-mathematica,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","Do

我有以下情况:

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. >>
[t::shdw]上的

消息[t::shdw,“t”,“Foobar”,“Dork”]
->t::shdw:符号t出现在多个上下文中;上下文Dork中的定义可能会隐藏或被其他定义隐藏。>>
关[t::shdw]
消息[t::shdw,“t”,“Foobar”,“Dork”]
->**没有警告**
>

这怎么可能?
打开
关闭
是否只影响当前笔记本,在加载软件包时不起作用?如果是这样的话,我们如何才能摆脱这样的信息呢?应该如何处理隐藏错误?

您观察到的原因是语句
Off[t::shdw]
禁用了当前位于
$ContextPath
上的符号
t
的隐藏消息,而不是加载另一个包期间创建的另一个
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
在这里,没有生成任何消息

但是,一般来说,我不想禁用阴影消息,因为阴影是一个严重的问题。阴影仅表示符号搜索路径(
$ContextPath
)上当前有多个上下文,其中包含具有相同(短)名称的符号。基本上,如果符号被阴影覆盖,并且您通过其短名称(即,没有包含其包的符号)引用它,您无法保证实际将使用具有相同短名称的多个符号中的哪一个。因此,正确的处理方法是完全避免阴影,这总是可能的,如果不总是方便的话

避免阴影的最简单方法是将所需的包加载到包的private部分,该部分在
Begin[“`private`]”行之后开始。您可以像往常一样通过调用
需要[您的包]
来实现这一点。这样,加载包的上下文就不会与包的上下文一起保留在
$ContextPath
上。最坏的情况是需要加载两个符号冲突的包。一种解决方法是为其中一个符号构造一个包装包,它将私自加载该符号并重命名冲突符号。但这可能会很不方便,因为您必须重命名包中的所有函数,即使是那些不冲突的函数。以下是一个更灵活的变体示例:

第一包:

BeginPackage["Test`"];
g[x_?NumericQ] := x^2;
EndPackage[];
第二套:

BeginPackage["Test1`"];
g[x_?NumericQ] := x^3;
EndPackage[]
主程序包:

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[]
现在,如果系统知道在哪里可以找到您的软件包:

In[2]:= Needs["Main`"]

In[3]:= f[x]
Out[3]= Test`g[x] Test1`g[x]

In[4]:= f[2]
Out[4]= 32
我们在同一个公共功能中使用了两个相互冲突的符号。使用上面的
Block
可以对使用
g
的第一个或第二个定义的代码进行本地化。请注意,此方法存在一些不便之处,因为我们需要使用
Symbol[“您的符号名称”]
,将解析延迟到运行时


一个非常简单的方法是只使用长名称引用符号。在上面,我们可以只使用
Test`g
Test1`g
,然后就不需要重型机械了。但是,这有点不够灵活,因为您必须将符号的上下文“硬编码”到代码中。

您可以重载
消息来关闭它:

Unprotect@Message;
Message[MessageName[s_, "shdw"],___] := Null;
Protect@Message;
此代码还发出一条更有用、更正确的消息,并使用Assert验证其断言:

Unprotect@Message;
Message[MessageName[s_, "shdw"], 
   rest : PatternSequence[snHeld_, pathsHeld_, newpath_]] := 
  With[{paths = ReleaseHold@pathsHeld},
   {memberpaths = Select[$ContextPath, MemberQ[paths, #] &], 
    sn = ReleaseHold@snHeld},
   Print@StringTemplate[
      "Note: Symbol `` added in context ``, so that it now appears in \
multiple contexts: ``. On the context path, it is currently found in: \
``. Definitions in the first context of the context path, ``, will \
shadow any other definitions."][sn, newpath, paths, memberpaths, 
     First@memberpaths];
   (*symbol name*)
   Assert[SymbolName@s === sn];

   (*demonstrate that First@
   memberpaths is the context used for short names*)
   Assert[ToExpression@StringTemplate[
       "Unevaluated@`` === Unevaluated@````"
       ][sn, First@memberpaths, sn
      ]
    ];

   (*and not any other context*)
   Assert@AllTrue[TrueQ][ToExpression@StringTemplate[
          "Unevaluated@`` =!= Unevaluated@````"
          ][sn, #, sn
         ] & /@ DeleteCases[paths, First@memberpaths]
     ];
   ];
Protect@Message;
尝试:

注意:符号图像添加到上下文全局`,因此它现在出现在多个上下文中:{Global`,System`}。在上下文路径上,它当前位于:{System`,Global`}。上下文路径的第一个上下文中的定义System`,将隐藏任何其他定义。


c、 f.

+1我刚刚输入了(几乎)完全相同的答案。。。一条评论:如果phantomas真的想关闭所有隐藏消息,他应该使用
off[General::shdw]
@Simon的确,我错过了这一条。@Leonid,看看我所做的更改,看看如何做到。@Leonid,“避免隐藏的最简单方法是将您需要的包加载到私有部分…”不知道这一点。这对我很有帮助,谢谢。以前,我正在阅读我的包中的另一个包(在私有部分之前),并手动将其从$ContextPath:-)中删除,现在好多了。@rcollyer谢谢,我读了,我收到了。
Global`Image