以下代码按预期返回14:
Block[{expr},
expr = 2 z;
f[z_] = expr;
f[7]]
但是,如果将
Block
更改为Module
,则它将返回2*z
。本地化除
expr
之外的其他变量似乎也没有关系。我以为我了解Mathematica中的Module,Block和With,但是在此示例中我无法解释Module和Block在行为上的区别。
相关资源:
Mathematica文档中的Tutorial on Modularity and the Naming of Things
摘录自book by Paul R. Wellin, Richard J. Gaylord, and Samuel N. Kamin
Explanation from Dave Withoff on the Mathematica newsgroup
PS:感谢Michael Pilat,Davorak和Bill White遵循这种奇怪的方法。
达沃拉克(Davorak)在此阐明并深入探讨了问题的实质:
Why would Mathematica break normal scoping rules in Module?
最佳答案
我对此也感到有些惊讶,但是我不认为这是一个错误。如果您仔细阅读reference page for Module
中的示例,在“可能的问题”部分下,有一点说明“在嵌套作用域中重命名变量”,并给出以下示例:
In[1]:= Module[{e = Expand[(1 + x)^5]}, Function[x, e]]
Out[1]= Function[x$, e$1194]
In[2]:= %[10]
Out[2]= 1 + 5 x + 10 x^2 + 10 x^3 + 5 x^4 + x^5
Function
是另一个定义范围的构造,例如Module
,因此在x
范围内将x$
重命名为Function
,类似于您在Trace
中找到的关于z
的内容。在定义
Module
的f
中,Set
是另一个类似的作用域构造,因此,当在z
内定义f
时,Module
被重命名,而在Block
内定义Module
时,不会重命名。遵循文档中该示例的建议,您可以从其各个部分构建函数的RHS,以避免对嵌套作用域进行词汇重命名:In[3]:= Clear[f, z]
In[4]:= Module[{expr},
expr = 2 z;
Set @@ {f[z_], expr};
f[7]]
Out[4]= 14
HTH!