Mathematica中的词汇和动态作用域:具有模块,具有和块的局部变量 [英] Lexical and dynamic scoping in Mathematica: Local variables with Module, With, and Block

查看:238
本文介绍了Mathematica中的词汇和动态作用域:具有模块,具有和块的局部变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码按预期返回14:

Block[{expr},
  expr = 2 z;
  f[z_] = expr;
  f[7]]

但是,如果将Block更改为Module,则它将返回2*z. 本地化除expr以外的其他变量似乎也没有关系. 我以为我了解Mathematica中的Module,Block和With,但是在这个示例中我无法解释Module和Block在行为上的区别.

相关资源:

PS::感谢 Michael Pilat 比尔·怀特(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^5 

Function是另一个类似于Module的作用域构造,因此在Function范围内将x在内部重命名为x$,类似于您在Trace中发现的关于z的内容. /p>

在定义fModule中,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]= 14

HTH!

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:

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^5 

Function 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]= 14

HTH!

这篇关于Mathematica中的词汇和动态作用域:具有模块,具有和块的局部变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆