programming-languages - 为什么 Mathematica 会破坏 Module 中的正常范围规则?

标签 programming-languages wolfram-mathematica

正如在最近的 post 中指出的那样作用域在 Module 内部无法按预期工作。

该线程的一个示例是:

Module[{expr},
 expr = 2 z;
  f[z_] = expr;
  f[7]]
(*2 z*)

但以下工作几乎按预期工作。
Module[{expr},
 expr = 2 z;
  Set@@{f[z_], expr};
  f[7]]
(*14*)

是什么语言设计考虑让 wolfram 选择了这个功能?

编辑:请参阅 Jefromi 的第一条评论,我将 z 从局部变量更改为非局部变量,并忘记更改输出。它不会影响问题。

编辑2:
Michael Pilat 的观点似乎是 Block 和 Module 具有不同的功能。我想我理解他的观点,但我认为这与我的问题是正交的。所以这里有一个更新。

我可以在笔记本的全局级别使用以下代码:
expr = 2 z;
f[z_] = expr;
f[7]
(*output: 14*)

但是,当我将相同的代码块放入模块并使 expr 成为本地时,它会产生不同的输出。
Clear[f];
Module[{expr},
 expr = 2 z;
 f[z_] = expr;
 f[7]]
(*output: 2z*)

如果你跟踪上面的 Module 调用,你会发现 Set[f[z_], expr] 被重写为 Set[f[z$_,expr]。现在这个 z->z$ 转换发生在 Set 的 lhs 和 rhs 上。然而,它发生在 expr 评估之前,这会导致在全局级别获得不同的结果。

转换 z->z$ 似乎仅在 rhs 具有 Module 调用的本地符号时发生。

为什么 Mathematica 选择在 Module 调用中更改此语法?这里存在哪些语言/实现设计权衡来做出这个决定。

最佳答案

我认为答案很简单,但很微妙:Module是一个词法作用域结构,Block是一个动态范围构造。

Blocks Compared With Modules文档中的教程讨论了区别:

When lexical scoping is used, variables are treated as local to a particular section of the code in a program. In dynamic scoping, the values of variables are local to a part of the execution history of the program. In compiled languages like C and Java, there is a very clear distinction between "code" and "execution history". The symbolic nature of Mathematica makes this distinction slightly less clear, since "code" can in principle be built up dynamically during the execution of a program.

What Module[vars, body] does is to treat the form of the expression body at the time when the module is executed as the "code" of a Mathematica program. Then when any of the vars explicitly appears in this "code", it is considered to be local. Block[vars, body] does not look at the form of the expression body. Instead, throughout the evaluation of body, the block uses local values for the vars.



它提供了这个简化的示例:
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

也许关键是要意识到 Module替换 i 的所有实例在具有本地化版本(例如 i$1234 )的模块主体中,在词法上,之前 实际上评估了模块的任何主体。

因此,实际评估的模块主体是 i$1234 + m ,然后 i$1234 + i^2 ,然后 a + i^2 .

什么都没有损坏,BlockModule旨在表现不同。

关于programming-languages - 为什么 Mathematica 会破坏 Module 中的正常范围规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2739643/

相关文章:

import - 删除 Mathematica 表中的空值

python - 开箱即用的软件是否将 GPU 用于数字?

programming-languages - 值得努力学习 D 吗?

programming-languages - 同形性究竟是什么意思?

wolfram-mathematica - 在 Mathematica 中求解两个变量递归方程,这可能吗?

list - 将 Mathematica 值列表转换为 boolean 值列表

wolfram-mathematica - 在 Mathematica 中获得数量级

compiler-construction - 解决循环导入问题

programming-languages - 用于实现决策树的语言

image-processing - 图像处理语言/环境