学习 Scala 时,我学到的第一件事就是每个函数都会返回一些东西。不存在像 Java 中那样的“void”函数/方法。因此,从数学角度来说,许多 Scala 函数都是真正的函数,并且对象在很大程度上可以保持无状态。
现在我了解到,Actor 模型是 Scala 等函数式语言中非常流行的模型。然而,参与者提倡“即发即忘”的编程风格,并且调用者通常不期望被调用者直接回复消息(除非使用“询问”/“?”方法)。因此, Actor 需要记住某种状态。
我是否正确地假设参与者模型更像是可扩展性和可维护性之间的权衡(由于其有状态性),有时甚至可以被视为反模式?
最佳答案
是的,你基本上是对的(当你说可扩展性与可维护性时,我不太确定你在想什么)。
Actor 在 Scala 中很受欢迎是因为 Akka(Akka 也很受欢迎,因为它得到了 Lightbend 的支持)。然而,事实并非如此, Actor 在函数式编程世界中普遍流行(尽管我正在考虑的所有语言都存在实现)。以下是我对另外两个 FP 语言社区的极其简化的印象(因此请谨慎对待),这两个社区使用 actor 的频率(远远低于 Scala)。
- Haskell 社区倾向于使用 STM/channels (通常在 STM context 中)。直线
MVar
s也令人惊讶地经常使用。 - Clojure 社区有时会吹捧自己的内置 STM 版本,但其旗舰并发模型实际上是
core.async
,这又是 channel 的核心。
作为旁白 STM, channel 和参与者都可以彼此分层;将它们进行比较有点奇怪,就好像它们是相互排斥的方法一样。但在实践中,很少看到它们全部同时使用。
Actor 确实涉及状态(在 Akka 裙子类型安全的情况下),因此非常具有表现力,并且几乎可以做任何并发方面的事情。通过这种方式,它们类似于副作用函数,比纯函数更具表现力。事实上, Actor 在某种程度上是面向对象的纯粹本质,既有优点也有缺点。
因此有一个 sizable chunk Scala 社区的一些人会说是的,如果大多数时候当你面临并发问题时,你都在使用 actor,那么这可能是一种反模式。
- 如果可以的话,尝试只使用
Future
或scalaz.concurrent.Task
。 In return for less expressiveness you get more composability. - 如果您的问题自然适合单一全局状态(例如,以您想要强制执行的全局不变量的形式),请考虑 STM。在Scala社区,虽然an STM library存在,我的印象是STM通常是通过使用actors来模拟的.
- 如果您的并发问题主要与流式传输多个数据源有关,请考虑使用 Scala 的 streaming 之一libraries .
关于scala - Actor 模型不是一种反模式吗,因为“一劳永逸”的风格迫使 Actor 记住一种状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40126263/