以下代码按预期返回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 PilatDavorakBill 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的内容。

在定义Modulef中,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!

09-05 11:17