我是 scala 和演员世界的新手。
这是我到目前为止所学到的:
Scala 是函数式编程(不是纯粹的),人们建议不要在 scala 中使用可变状态。
但另一方面,有一个akka框架实现了actor模型。在玩 akka 的过程中,我意识到消息是不可变的,但演员的状态是可变的。所以,我需要在演员内部指定“var”变量和可变集合。而且,对我来说,拥有可变状态对于 scala 来说是不自然的。
那么,我的理解正确吗?为什么人们采用不可变的 Scala 语言中的可变演员模型?
我是 scala 和演员世界的新手。
这是我到目前为止所学到的:
Scala 是函数式编程(不是纯粹的),人们建议不要在 scala 中使用可变状态。
但另一方面,有一个akka框架实现了actor模型。在玩 akka 的过程中,我意识到消息是不可变的,但演员的状态是可变的。所以,我需要在演员内部指定“var”变量和可变集合。而且,对我来说,拥有可变状态对于 scala 来说是不自然的。
那么,我的理解正确吗?为什么人们采用不可变的 Scala 语言中的可变演员模型?
这是一个有趣的观点,并且确实演员与其他类似 Scala 的代码完全不同。
您可以将参与者视为具有锁、信号量等的线程的替代品。它是一种更直观、更高效的并发编程模型,因为可变状态总是封装在一个按顺序处理消息的参与者中。
它为构建更多功能抽象提供了坚实的基础。Akka 团队制作了 akka-streams。Spark 使用 akka 跨节点通信。Future
s,该问题的另一个成功的功能替代方案本质上是流的一种特殊情况:只有一个元素的流,并且可以使用参与者来实现。
因此,人们使用 Actor 是因为通过让 Actor 相互发送消息而不是对流进行操作,可以更直观地解决一些问题。由于反对可变性的主要论据是它在并发上造成的完全混乱,而参与者正是解决了这个问题,我想拥有这种可变性是可以的。它们相当复杂,但并发的正确解决方案实际上就是这么复杂。
请注意,流可以说是模拟程序与其环境的任何交互的功能方式。例如,对于 GUI 开发,您可以将控件的所有触发事件作为流提供,折叠流本质上是创建一种管理程序状态的方法。
这是一个很好的问题,有一个有趣的答案(恕我直言):Scala 不起作用。它是后功能的。这意味着它将面向对象和函数式编程统一为一个范式。
在这个框架内,Scala 支持不变性,但不强制执行它。Actor 模型是可变性有意义的地方,因为所有更改都是本地的,并发行为的协调由 Actor 系统为您完成。
Scala 是一种允许混合模型的语言。确实,大多数示例在 Actors 中使用可变状态,但您可以使用具有不可变状态的 Actors 使用become
:
class ListActor extends Actor {
def receive = changeState(List.empty[String])
def changeState(state: List[String]): Receive = {
case Add(item) =>
context.become(changeState(item :: state))
}
}