使用不变性进行设计(在 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)是仅相等还是引用相同是理论上的区别。
由于 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)是仅相等还是引用相同是理论上的区别。