以下代码按预期返回14:
Block[{expr}, expr = 2 z; f[z_] = expr; f[7]]但是,如果将Block更改为Module,则它将返回2*z. 本地化除expr以外的其他变量似乎也没有关系. 我以为我了解Mathematica中的Module,Block和With,但是在这个示例中我无法解释Module和Block在行为上的区别.
相关资源:
- Mathematica文档中的有关模块化和事物命名的指南
- 摘录自书
- Mathematica新闻组上Dave Withoff的解释
PS::感谢 Michael Pilat ,达沃拉克(aavo)和比尔·怀特(bill White)怪异的气味. 达沃拉克(Davorak)在此阐明并深入探讨了问题的实质: 为什么Mathematica会破坏模块中的常规作用域规则?
解决方案对此我也感到有些惊讶,但是我不认为这是一个错误.如果您仔细阅读参考页中的示例, 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^5Function是另一个类似于Module的作用域构造,因此在Function范围内将x在内部重命名为x$,类似于您在Trace中发现的关于z的内容. /p>
在定义f的Module中,Set是另一个类似的作用域构造,因此,当在Module内定义f时,z被重命名,但在Block内定义时却没有重命名. >.遵循Module文档中该示例的建议,您可以从函数的各个部分构建函数的RHS,以避免对嵌套作用域进行词汇重命名:
In[3]:= Clear[f, z] In[4]:= Module[{expr}, expr = 2 z; Set @@ {f[z_], expr}; f[7]] Out[4]= 14HTH!
The following code returns 14 as you'd expect:
Block[{expr}, expr = 2 z; f[z_] = expr; f[7]]But if you change that Block to a Module then it returns 2*z. It seems to not matter what other variables besides expr you localize. I thought I understood Module, Block, and With in Mathematica but I can't explain the difference in behavior between Module and Block in this example.
Related resources:
- Tutorial on Modularity and the Naming of Things from the Mathematica documentation
- Excerpt from a book by Paul R. Wellin, Richard J. Gaylord, and Samuel N. Kamin
- Explanation from Dave Withoff on the Mathematica newsgroup
PS: Thanks to Michael Pilat, Davorak, and Bill White for following the scent-trail on this weirdness. Davorak clarifies and gets to the heart of the issue here: Why would Mathematica break normal scoping rules in Module?
解决方案I too was a bit surprised by this, but I don't think it's a bug. If you look deep in the examples in the reference page for Module, under the section labeled Possible Issues, there's a little note that says "Variables are renamed in nested scopes" and gives the following example:
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^5Function is another scoping construct like Module, so x is renamed internally to x$ in the scope of the Function, similar to what you discovered with Trace about z.
In your Module defining f, Set is another such scoping construct, and therefore z is renamed when f is defined inside of a Module, but not when it's inside a Block. Following the advice of that example from the Module documentation, you can build the RHS of your function from its parts to avoid the lexical renaming of the nested scope:
In[3]:= Clear[f, z] In[4]:= Module[{expr}, expr = 2 z; Set @@ {f[z_], expr}; f[7]] Out[4]= 14HTH!
更多推荐
Mathematica中的词汇和动态作用域:具有模块,具有和块的局部变量
发布评论