可变或不可变的闭包

时间:2009-04-04 19:38:20

标签: language-design closures immutability mutable

在命令式,对象定位语言中,拥有可变或不可变的闭包会更有意义吗?

例如:

int i=5;
function() f={print(i);};
f();
i=6;
f();

如果闭包是可变的,则会打印:

5
6

如果它是不可变的,则会打印:

5
5

我意识到即使使用不可变闭包,你仍然可以这样做:

class I {int i;}
I i=new I();
i.i=5;
function() f={
    I j=i;
    print(j.i);
};
f();
i.i=6;
f();

那么,拥有可变或不可变的闭包,或者两者都有选择会更好吗?不可变的闭包似乎更容易实现,所以在这一点上,我想我会继续使用它,除非有充分的理由不这样做。

2 个答案:

答案 0 :(得分:4)

命令式语言通常围绕国家概念构建。因此,语言功能更有意义地反映这一点,包括闭包。是的,这种行为有时会令人困惑,但在应用程序中使用状态是问题和优势的一部分。

我认为这个论点的最好证明是看一些最近有闭包支持的语言。 C#和VB.Net,命令式OO语言都选择了可变闭包。虽然F#是一种函数式语言,但它具有不可变的闭包(主要源于F#默认是不可变的)。

在命令式语言中使用不可变闭包实际意味着什么呢?大多数人认为这使得变量等同于C#的readonly。确保值类型不受修改,但可变引用类型如何。您将无法更改变量指向的位置,但您可以调用变异函数并获得类似的效果。例如。

class Student {
  public string Name { get; set; }
}

void Example() {
  var student = new Student() { Name = "foo" };
  Action() del = () => 
    { student.Name = "bar"; };
  del();
}

这可以使用不可变闭包来实现,因为我实际上并没有修改变量指向的位置。但是我显然仍在进行变异操作。

答案 1 :(得分:3)

应该是语言有lambda是按值获取还是通过引用捕获?请自行决定,但请参阅“On lambdas, capture, and mutability”以获取更多评论。