Mathematica中的包导入问题

5

在Mathematica中(我使用的是相当古老的MMA 5.0),如果我将以下内容作为一行输入:

Needs["Graphics`Master`"]; Animate[Plot[Sin[n x], {x, 0, 2 Pi}, Axes -> False], {n, 1, 6, 1}]

我遇到了很多错误/警告。但是如果我单独输入它们,就能正常工作。如何使它在一个代码块中工作呢?
谢谢!
2个回答

12

正如Belisarius所指出的那样,你的问题在目前版本中有些偏向于v5。然而,这个问题在当前版本中仍然存在。以下是一个示例:

Needs["Combinatorica`"]
ToCycles[{3, 4, 1, 2}]

运行良好,但(重新启动内核后)

Needs["Combinatorica`"]; ToCycles[{3, 4, 1, 2}]

出现错误:

"ToCycles::shdw: 符号 ToCycles 在多个上下文 {Combinatorica`,Global`} 中出现;在上下文 Combinatorica` 中的定义可能被其他定义屏蔽或屏蔽其他定义。"

在Mathematica中,这个一行代码不能正常工作是因为Mathematica在评估Needs之前会尝试解析该行中的所有符号(对我来说这是一个惊喜)。这将把ToCycles解析为Global`ToCycles(从而将该符号输入符号表),而在Needs有机会加载Combinatorica`ToCycles的定义并将Combinatorica添加到$ContextPath之前。要使这个一行代码正常工作,必须使用完整名称ToCyles

Needs["Combinatorica`"]; Combinatorica`ToCycles[{3, 4, 1, 2}]
为了理解这个错误,你需要知道 Mathematica 中的所有符号都具有形式为 context`name全名。一个上下文类似于许多其他语言中的命名空间。现在,如果一个符号(比如 ToCycles)没有指定上下文,Mathematica 将查找当前在 $ContextPath 中的上下文,并查看该符号是否在任何其中定义。如果没有,则该符号将在当前上下文 $Context 中解析,而在正常使用中它是Global
当你加载一个包时,该包的符号被定义在一个包上下文中(例如 Combinatorica),并且当包被完全加载后,该上下文会被添加到$ContextPath 中,以便您可以通过其简短名称访问符号。
现在,你可以看到这个错误的含义:由于在解析这些符号时还没有加载 Combinatorica 包,因此 ToCycles 被解析为 Global`ToCycles。在包被加载后,Mathematica 会检查所有简短名称是否唯一,并发现在这种情况下简短名称 ToCycles 现在定义在 $ContextPath 的两个上下文中,一个"遮蔽"了另一个。要引用这些符号的特定之一,必须使用全名,例如Combinatorica`ToCycles
为了解决阴影冲突,只需使用 Remove 去除不需要的符号即可。
Remove[Global`ToCycles]

不知道这个是否易读,但希望能对你有所帮助...


1
讲解得很清楚!令人惊讶的是,天真的一行代码并不能起作用。 - Simon
1
@Quang Li:在Combinatorica和ToCycles之间必须使用“反引号”,但我花了一些时间才弄清楚如何输入文字中的反引号。现在应该没问题了吧?此外,我在看到你的评论之前就已经添加了正确的一行代码 :) - Janus
1
@Simon:谢谢!这也让我感到惊讶。我一直以为分号和换行是完全可互换的... - Janus
1
+10 从来没有发生过这种情况...因为我总是单独在一行中使用Needs[]...知道原因真是太好了! - Dr. belisarius
原来 ; 实际上是 CompoundExpression 的简写,这就是为什么事情会有所不同的原因。不过,符号解析并没有真正包含在 http://reference.wolfram.com/mathematica/tutorial/Evaluation.html 中 :) - Janus
显示剩余2条评论

2

你需要把Needs[]函数放在笔记本的顶部作为单独的模块,或者放在package.m文件的第一行。

内核会读取整行并解析它,包括为符号决定上下文,然后才开始评估它。为避免问题,请不要使用分号。 在包中的每个语句后面都要放置两个换行符,尤其是在BeginPackage[]和/或Needs[]之后。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接