首页 > 解决方案 > 整个程序可以是不可变的吗?

问题描述

不可变对象链

问题:假设 mutator 调用来自不可变对象,如何处理这个新对象?

问题:这在哪里停止?是否必须在某个地方有一个可变对象才能至少保存最顶层的实例?

标签: javaimmutability

解决方案


这就是函数式编程的思想。一切都是不可变的,任何函数调用都不允许有副作用。改变复杂对象的唯一方法,就像在你的例子中一样,是重新创建父对象。

现在的问题是如何改变程序状态。因此,我们首先考虑堆栈。它包含所有局部变量的值以及被调用函数的所有参数的值。我们可以通过调用新函数来创建新值。我们可以通过从函数返回来丢弃值。因此,我们可以通过调用函数来改变程序状态。但是,从函数返回时并不总是可以丢弃它的局部变量,因为我们可能只想丢弃一些局部变量,但需要保留其他变量的值以进行进一步的操作。在这种情况下,我们根本无法返回,但我们需要调用另一个函数并只将一些局部变量传递给它。现在,为了防止堆栈溢出,函数式语言有一个称为尾调用优化的特性,它能够从调用堆栈中删除不必要的条目。如果对关联函数剩下要做的唯一事情是返回其自身调用的函数的值,则调用堆栈的条目是不必要的。在这种情况下,保留调用堆栈条目是没有意义的。通过删除不必要的调用堆栈条目,其他未使用的局部变量的值将被丢弃。您可能想了解它在这里。此外,尾递归与此有关。

同样,这是像Haskell这样的纯函数式编程语言的想法。一切都是不可变的,这真是太好了,但是这些语言有它们唯一的问题和它们自己处理这些问题的方法。例如,在这些语言中可以使用 Monad(以及因此更高种类的类型),但在命令式/面向对象的编程语言中很少见。

我喜欢在我的程序内存的叶子上拥有不可变的值。但是,构成这些不可变值的代码(实际上形成了应用程序逻辑)确实包含可变状态。对我来说,这结合了两个世界的优点。然而,这似乎是一个偏好问题。


推荐阅读