language-design - 可变或不可变闭包

标签 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();

那么,是可变闭包还是不可变闭包更好,还是两者都有?不可变闭包似乎更容易实现,所以在这一点上,我想我会采用它,除非有充分的理由不这样做。

最佳答案

命令式语言通常围绕状态概念构建。因此,语言特性反射(reflect)这一点更有意义,包括闭包。是的,这种行为有时会令人困惑,但它是问题的一部分,也是在您的应用程序中拥有状态的优势。

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

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

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

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

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

关于language-design - 可变或不可变闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/717669/

相关文章:

ios - 返回另一个 block 内的 block 有时会延迟

python - 根据参数动态调用嵌套函数

python - 为什么不使用 "is"比较来代替原始类型的 "=="?

java - .NET 中的不可变列表 : Why are you allowed to add and remove items?

c++ - 功能/不可变数据结构在非垃圾收集上下文中是否仍然对并发有用?

javascript - 真的被javascript es6箭头函数的 "enclosing scope"搞糊涂了

c++ - 为什么要设计一种具有独特匿名类型的语言?

c - 为什么 switch 语句设计为需要中断?

extjs - 如何正确地从另一个 Controller 或闭包调用 Controller 方法