8

我陷入了两难境地,请使用以下用 ML 编写的代码:

val x = 1
fun f(y) = x + y
val x = 2
val y = 3
val z = f (x + y)

z 的值为 6。现在,如果我在 python 中编写相同的代码,z 的值为 7。两种语言都声称(实际上教授这些语言的教师声称)具有词法/静态范围。但看起来只有 ML 通过使用在调用 f 时定义 f 函数时创建的环境来拥有它

任何指针将不胜感激!

谢谢!

4

2 回答 2

7

在 Python 中,闭包是按变量而不是按值。因此,当您x在函数中引用时,它指的是最近分配给x的值,而不是x定义函数时的值。这会得到非直观的结果,如下所示:

adders = []
for x in range(10):
    adders.append(lambda y: x+y)

您打算创建一个添加x到值的函数列表,其中x从 0...9 变化,但它们都添加 9,因为这是x循环结束时的值。

您可以通过使用默认参数将名称绑定到函数定义时的值来覆盖它。

x = 1
f = lambda y, x=x: x + y   # x inside f is now locked at 1
x = 2
y = 3
z = f(x + y)

在这个例子中,你甚至没有真正处理闭包:x这里实际上是一个全局变量。在 Python 中,只有在另一个函数内部定义了一个函数,并且顶级或模块全局命名空间不是函数时,才能创建闭包。但同样的原则也适用:全局变量显然可以在函数定义后更改,所以如果你想在函数定义时“锁定”它的值,你可以使用默认参数。

于 2013-10-27T20:06:30.900 回答
6

在 ML 中——至少在 ML 的功能部分中——没有变量赋值之类的东西。一旦你声明了那个val x = 1,你就不能改变那个的值x

但是,您可以做的是声明另一个x. 当您说 时val x = 2,您正在引入一个名为 的全新变量x,它基本上只是隐藏了旧变量。但是该函数f已经被定义为指向原始的x,所以它不受影响。

ML 确实支持可变类型,可以像 Python 中的变量一样重新分配。但是它们与功能范式相差甚远,以至于您几乎没有任何理由使用它们。如果你想这样编程,Python 是一种更好的语言。

于 2013-10-28T09:26:04.930 回答