使用不变性进行设计(在 Scala 中)

Designing with immutability (in Scala)

由于 Scala 等编程语言强调不变性(避免 "var"),这是否意味着我的对象中的 "state-modifying methods" 必须 return 实例的副本(使用新状态)?

让我们考虑乌龟。我想这样移动我的乌龟:

val turtle = new Turtle(0, 0, "north")
val turtle2 = turtle.turnLeft().forward(5).turnRight().backward(2)

这里 turtle2 不会指向同一个 Turtle 实例(它们是两个独立的实例)。事实上,在这个动作序列中,创建了 4 个临时对象。这就是我实现方法 turnLeft 的方式,例如:

def turnLeft {
  self.copy(orientation = self.orientation match {
    case "north" => "west"
    case "east" => "north"
    case "south" => "east"
    case "west" => "south"
  })
}

这是正确的设计方法吗?

如果是,那(在每次方法调用时创建新对象)效率/低效如何? 如果不是,那正确的是什么?我对不变性方面(或者一般的函数式编程)的理解有什么问题/缺失?

提前致谢, 拉卡

创建大量短暂的对象是 Scala 的标志性功能。它通常不是很昂贵,前提是您 运行 在具有足够大小的堆的 JVM 上使用它,并具有足够的新生代内存来容纳所有的流失。

话虽如此,不变性不是一种宗教。常识应该占上风,并在坚持 "paradigm" 变得过于费力的情况下指导设计决策。

我认为,考虑是否要将 Turtle 作为一个实体来处理很重要。

如果我有一辆车,我向右转动方向盘,汽车向右行驶(在最佳情况下:P),然后我向左转动方向盘,它向左行驶,但它仍然是同一辆车。乌龟也是如此。虽然不变性通常使程序更容易理解,但在某些情况下它不太直观。

想一想右航海龟和左航海龟是否不同。当然,相等检查是可以被覆盖的,所以新旧海龟(具有相同name/id)是仅相等还是引用相同是理论上的区别。