避免可变变量和其他副作用的纯函数程序的一大特性是表达式计算的值仅取决于表达式本身。它不取决于评估事物的顺序(从左到右、从右到左、严格、惰性)、操作系统的状态、一天中的时间等。
特别是,这意味着在纯函数设置中,每次调用都new C
将返回一个完全相同的计数器对象。这通常是一件好事,因为它可以更容易地推理你的程序,但它会妨碍你在那里尝试做的事情。要使 C 对象与众不同,您需要显式传递它们的计数器值,老实说,这只是在解决问题。
val c1 = new C(0)
val c2 = new C(1)
如果你想拥有一个像内部类变量一样的全局“计数器”变量,你正在使用一种可能的方法来在纯函数设置中实现它,将计数器值传递给每个需要计数器的函数并让这些函数也返回计数器的更新版本。举个简单的例子:
def increment_counter(n: Int): Int = { n + 1)
def create_c(n: Int): (C, Int) = {
val c = new C(n)
val n' = increment_counter n
(c, n')
}
val n = 0
val (c1, n') = create_c(n)
val (c2, n'') = create_c(n')
val n' = increment_counter(n)
您可以使用 State Monad 模式更好地构造它(大多数对 monad 的介绍可能都会以此为例)。
但是,它很可能最终会比仅使用可变变量作为计数器更复杂。事实上,我通常在允许我这样做的功能语言中为这些“全局递增计数器”使用可变变量。