Dav*_*rak 7 programming-languages wolfram-mathematica
正如在最近的一篇文章中所指出的那样,范围内的模块不能按预期工作.
该线程的一个例子是:
Module[{expr},
expr = 2 z;
f[z_] = expr;
f[7]]
(*2 z*)
Run Code Online (Sandbox Code Playgroud)
但以下工作几乎与预期一致.
Module[{expr},
expr = 2 z;
Set@@{f[z_], expr};
f[7]]
(*14*)
Run Code Online (Sandbox Code Playgroud)
什么语言设计考虑使wolfram选择此功能?
编辑:请参阅Jefromi的第一条评论我将z从局部变量更改为not并忘记更改输出.它不会影响问题.
编辑2:Michael Pilat的观点似乎是Block和Module具有不同的功能.我想我理解他的观点,但我认为这与我的问题是正交的.所以这是一个更新.
我可以在笔记本中的全局级别使用以下代码:
expr = 2 z;
f[z_] = expr;
f[7]
(*output: 14*)
Run Code Online (Sandbox Code Playgroud)
但是当我将相同的代码块放入模块并使expr本地时,它会产生不同的输出.
Clear[f];
Module[{expr},
expr = 2 z;
f[z_] = expr;
f[7]]
(*output: 2z*)
Run Code Online (Sandbox Code Playgroud)
如果跟踪上面的模块调用,则会发现Set [f [z_],expr]被重写为Set [f [z $ _,expr].现在这个z-> z $转换发生在Set的lhs和rhs上.然而,它在expr被评估之前发生,这导致在全局级别获得不同的结果.
只有当rhs具有Module调用的本地符号时,才会发生转换z-> z $.
为什么Mathematica选择在模块调用中更改此语法?做出这个决定的是什么语言/实现设计权衡.
我认为答案很简单,但很微妙:Module是一个词法范围构造,Block是一个动态范围构造.
将随着组件相比块从文档教程介绍的区别:
当使用词法作用域时,变量被视为程序中代码的特定部分的本地变量.在动态范围中,变量的值对于程序的执行历史的一部分是本地的.在诸如C和Java的编译语言中,"代码"和"执行历史"之间存在非常明显的区别.Mathematica的符号性质使得这种区别稍微不那么明确,因为"代码"原则上可以在程序执行期间动态构建.
Module[vars, body]在将模块作为Mathematica程序的"代码"执行时,处理表达式主体的形式是什么.然后当任何变量显式出现在这个"代码"中时,它被认为是本地的.Block[vars, body]不看表达体的形式.相反,在整个身体评估中,块使用变量的局部值.
它提供了这个简化的例子:
In[1]:= m = i^2
Out[1]= i^2
(* The local value for i in the block is used throughout the evaluation of i+m. *)
In[2]:= Block[{i = a}, i + m]
Out[2]= a + a^2
(* Here only the i that appears explicitly in i+m is treated as a local variable. *)
In[3]:= Module[{i = a}, i + m]
Out[3]= a + i^2
Run Code Online (Sandbox Code Playgroud)
或许关键的一点是要认识到Module替换的所有实例i在模块机身采用了本地化版本(例如i$1234)词汇,之前的任何模块的身体的实际评价.
因此,i$1234 + m然后i$1234 + i^2,实际评估的模块体a + i^2.
什么都没有打破,Block并且Module打算表现不同.
根据文档,Module具有 属性HoldAll,这会导致 内的所有内容Module保持未评估状态,因此在分配给之前expr不会评估您的。2 zexprf[z_]
将第二个参数包装到ModuleinEvaluate似乎可以解决问题:
In[1]:= Module[{expr}, Evaluate[expr = 2 z;
f[z_] = expr;
f[7]]]
Out[1]= 14
Run Code Online (Sandbox Code Playgroud)
另外,使用Block而不是Module有效:
In[2]:= Block[{expr = 2 z},
f[z_] = expr;
f[7]]
Out[2]= 14
Run Code Online (Sandbox Code Playgroud)