如何全局关闭隐藏消息(符号::shdw)?或任何其他“良好实践”;建议?
我有以下情况:
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. >>
怎么可能? On
和Off
是否只影响当前Notebook,加载包时没有任何效果?如果是这样,如何摆脱这样的消息呢?应该如何处理阴影错误?
I have the following situation:
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. >>
How can that be? Does On
and Off
only affect the current Notebook and have no effect when loading packages? If so, how can one get rid of messages like these? How should shadowing errors be treated?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您观察到的原因是语句
Off[t::shdw]
禁用了当前位于$ContextPath< 上的符号
t
的隐藏消息/code>,但不适用于在加载另一个包期间创建的另一个t
。如果您不想看到第二个t
,您应该禁用它。这是一个示例:这里没有生成任何消息。
不过,一般来说,我不想禁用隐藏消息,因为隐藏是一个严重的问题。隐藏只是意味着符号搜索路径 (
$ContextPath
) 上当前存在多个上下文,其中包含具有相同(短)名称的符号。基本上,如果符号被隐藏,并且您通过其短名称引用它(即,不包含其包含包的符号),您无法保证具有相同短名称的几个符号中的哪一个实际上将被使用。因此,处理这个问题的正确方法是完全避免阴影,这总是可能的,尽管并不总是方便。避免阴影的最简单方法是将所需的包加载到包的私有部分,该部分在
Begin["`Private`"]
行之后开始。与往常一样,您可以通过调用Needs[your-package]
来完成此操作。这样,加载的包的上下文不会与包的上下文一起保留在$ContextPath
上。最糟糕的情况是当您需要加载两个具有冲突符号的包时。一种解决方法是为其中之一构建一个包装程序包,该包装程序包将私下加载该程序包并重命名冲突的符号。但这可能很不方便,因为您必须重命名包中的所有函数,即使是那些不冲突的函数。下面是一个更灵活变体的示例:第一个包:
第二个包:
主包:
现在,假设系统知道在哪里可以找到您的包:
我们对同一个公共函数使用了两个冲突的符号。使用上面的
Block
可以本地化使用g
第一个或第二个定义的代码。请注意,此方法有一些不便,因为我们需要使用Symbol["your-symbol-name"]
将解析延迟到运行时。一个非常简单的方法是仅通过符号的长名称来引用它们。在上面,我们可以只使用
Test`g
和Test1`g
,然后就不需要重型机械了。然而,这有点不太灵活,因为您必须将符号的上下文“硬编码”到代码中。The reason for what you observed is that the statement
Off[t::shdw]
disables a shadowing message for the symbolt
that is currently on the$ContextPath
, but not for anothert
, created during the loading of another package. You should disable shadowing message for that secondt
, if you don't want to see it. Here is an example:Here, no message was generated.
Generally, however, I would not want to disable shadowing messages, since shadowing is a serious problem. Shadowing simply means that there is more than one context currently on the symbol search path (
$ContextPath
), containing symbol(s) with the same (short) name. Basically, if symbol is shadowed, and you refer to it by its short name (that is, symbol without its containing package), you have no guarantee which of the several symbols with the same short name will actually be used. So, the correct way to deal with this is to avoid shadowing altogether, which is always possible, if not always convenient.The simplest way to avoid shadowing is to load the package you need into the private section of your package, which starts after the line
Begin["`Private`"]
. You do that by callingNeeds[your-package]
, as always. In this way, the context of the loaded package does not stay on the$ContextPath
together with your package's context. The worst case is when you need to load two packages with conflicting symbols. One way out is to construct a wrapper package for one of them, which would load that one privately and rename the conflicting symbols. This may be inconvenient though, since you'd have to rename all functions in a package, even those that don't conflict. Here is an example of a more flexible variant:First package:
Second package:
Main package:
Now, provided that the system knows where to find your packages:
And we used two conflicting symbols for the same public function. Using
Block
above served to localize the code where the first or second definition ofg
is used. Note that there is some inconvenience with this method in that we need to useSymbol["your-symbol-name"]
, to delay the parsing until run-time.A much simple method is to just refer to symbols by their long names. In the above, we could just use
Test`g
andTest1`g
and then there is no need for the heavy machinery. This is somewhat less flexible however, since you have to "hard-code" the symbol's context into the code.您可以重载
Message
将其关闭:此代码还会发出更有用且更正确的消息,并使用 Assert:
Try 验证其断言:
cf https://mathematica.stackexchange.com/questions/43381/result-about-context-is-inconcient-with-the-description-of-power-programming/119887#119887
You can overload
Message
to turn it off:This code also emits a more helpful and correct message, and it verifies its assertions with Assert:
Try:
c.f. https://mathematica.stackexchange.com/questions/43381/result-about-context-is-inconsistent-with-the-description-of-power-programming/119887#119887