Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Localization Mathematica中的词汇和动态范围:带模块、带和块的局部变量_Localization_Variables_Module_Scope_Wolfram Mathematica - Fatal编程技术网

Localization Mathematica中的词汇和动态范围:带模块、带和块的局部变量

Localization Mathematica中的词汇和动态范围:带模块、带和块的局部变量,localization,variables,module,scope,wolfram-mathematica,Localization,Variables,Module,Scope,Wolfram Mathematica,以下代码返回14,正如您所期望的那样: Block[{expr}, expr = 2 z; f[z_] = expr; f[7]] 但是如果您将块更改为模块,那么它将返回2*z。 除了本地化expr之外,其他变量似乎并不重要。 我想我理解Mathematica中的模块、块和With,但我无法解释这个例子中模块和块之间的行为差异 相关资源: 来自Mathematica文档 摘自 PS:感谢、、和对这一奇怪现象的追踪。 达沃拉克在此澄清并触及问题的核心: 您在这两个表达式上都使用

以下代码返回14,正如您所期望的那样:

Block[{expr},
  expr = 2 z;
  f[z_] = expr;
  f[7]]
但是如果您将
更改为
模块
,那么它将返回
2*z
。 除了本地化
expr
之外,其他变量似乎并不重要。 我想我理解Mathematica中的模块、块和With,但我无法解释这个例子中模块和块之间的行为差异

相关资源:

  • 来自Mathematica文档
  • 摘自
PS:感谢、、和对这一奇怪现象的追踪。 达沃拉克在此澄清并触及问题的核心:

您在这两个表达式上都使用了跟踪吗?

首先,我认为您暴露了一个错误

其次,我想我可以提供一些关于为什么会发生这种情况的见解,记住我对mathematica的内部知识是有限的

像:f[z_]:=2 z这样的完整形式的语句是:

SetDelayed[f[Pattern[z, Blank[]]], 2 z]
这会将下降值[f]设置为:

{HoldPattern[f[z_]] :> 2 z}
然后,当一个表达式(如f[2])稍后被计算时,将执行以下操作:

f[2] /. HoldPattern[f[z_]] :> 2 z
这将评估为4。现在这一切都是可能的,因为模式匹配是在第一个代码块的模式[z,Blank[]下进行的。即使您已经将z设置为一个数字,这仍然有效。换句话说

z = 5;
f[z_] := 2*z
仍然为f生成相同的下行值:

{HoldPattern[f[z_]] :> 2 z}
这是可能的,因为模式具有HoldFirst属性

如果在模块内对此进行求值,则HoldFirst属性不足以提供保护。 例如:

产出:

tmp[expr$8129]
我建议,因为HoldFirst属性不提供模块变量重写规则的豁免权,所以包含局部变量的规则中的任何模式都会重写其模式变量。符号->符号[SymbolName[sym]~“$”]

在简单的alpha转换中,在规则的两侧都重写了z

如果规则不包含局部变量,则不会进行重写:

Module[{expr},
 Hold[z_ -> (z)]
]
(*Hold[z_ -> z]*)
应用上述总括规则,而不是搜索局部变量是否与规则变量匹配

因此,问题在于,在阿尔法转换发生之前,不会对局部表达式进行求值。或者,更好的方法是将expr包装在一个延迟评估的alpha转换中,这对于规则延迟来说是必需的

这不会发生在块中,因为块不会重写任何局部变量

还有其他想法吗?
有人看到我的逻辑有漏洞吗?

我对此也有点惊讶,但我不认为这是一个错误。如果您深入查看中的示例,在标记为可能问题的部分下,有一个小注释说“变量在嵌套范围内重命名”,并给出以下示例:

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 
函数
是另一个作用域构造,类似于
模块
,因此
x
函数
的范围内被内部重命名为
x$
,类似于您在
跟踪
中发现的关于
z
的内容

模块
定义
f
中,
是另一个这样的作用域构造,因此当
f
模块
内定义时,而不是在
内定义时,
z
被重命名。按照
模块
文档中该示例的建议,您可以从函数的各个部分构建RHS,以避免对嵌套范围进行词法重命名:

In[3]:= Clear[f, z]

In[4]:= Module[{expr},
  expr = 2 z;
  Set @@ {f[z_], expr};
  f[7]]

Out[4]= 14

啊,聪明!因此,
z$
在模块版本中变成了
z$
。所以我想这就解释了,但我还是不明白为什么会这样!也许我会更新这个问题,专门问一下这个奇怪的问题。非常感谢,达沃拉克。你和迈克尔·皮拉特似乎在讨论同一个问题,对吧?这是同一个问题。alpha转换提供了函数、规则、集合、SetDelayed的作用域,但重写的变量仍在全局名称空间中。我想我错了,我认为这是一个错误,但这是相当恼人的。哇,不是我所说的一个漂亮的工作,而是令人印象深刻的工作,找出了这一点!这就是为什么我每天都这样回来。向我学习了一些s**t:-)。我宁愿让expr包装在一个懒惰的alpha转换中,而不是处理不一致的语法,以承受意外的性能损失。这里要考虑的语言设计因素是什么?这项工作并不完美,因为集合的HoldFirst属性不再持有f[z_2;]。如果在未清除f的情况下对示例代码求值两次,则会出现set::write错误。很好地抓住了Michael Pilat.Davorak,对,但是您可以使用,例如
Set@@Hold[f[z],expr]
来避免这个问题。或者,您可以使用
f=Function@@@z,expr}
也许我们也需要开始使用Perl的TMTOWTDI for Mathematica=)我不能谈论子作用域重命名行为背后的确切考虑因素,除了
f[z]=…
实际上是指希望将
z
视为
f
定义中的局部变量,而重命名(有时是不必要的)确保了这一点。
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 
In[3]:= Clear[f, z]

In[4]:= Module[{expr},
  expr = 2 z;
  Set @@ {f[z_], expr};
  f[7]]

Out[4]= 14