我正在寻找一个允许我使用的轻量级库,而不是编写:
val future1 = process1()
future1.onSuccess { process2() }
以下:
val future1 = process1()
future1.await()
process2()
不阻塞线程(所以不是Await.result(future1)
:)也就是说,我正在想象一个基于延续的库,它将后者转换为前者。
我正在寻找一个允许我使用的轻量级库,而不是编写:
val future1 = process1()
future1.onSuccess { process2() }
以下:
val future1 = process1()
future1.await()
process2()
不阻塞线程(所以不是Await.result(future1)
:)也就是说,我正在想象一个基于延续的库,它将后者转换为前者。
这个问题是一年前提出的。今天,比 Akka Dataflow 更有前途的替代方案是scala-async,可在https://github.com/scala/async获得。
Akka Dataflow 依赖于 continuation 插件,该插件没有被积极维护并且正在弃用。
另一方面,scala-async并没有尝试成为通用的 cps 解决方案,而只是处理异步代码的编写(我相信这恰好是 cps 插件最常见的用例)。换句话说,它直接实现了 Akkaflow
方法的等价物(在宏的帮助下),因此它的范围比 cps 插件更窄(并且定义更好),我认为这是让它成为一个更好的整体实现的关键。
这是从自述文件页面中获取的示例:
val future = async {
val f1 = async { ...; true }
val f2 = async { ...; 42 }
if (await(f1)) await(f2) else 0
}
看看Akka Dataflow Concurrency。看起来正是你想要的!
示例(请参阅文档):
flow {
val f1 = flow { "Hello" }
val f2 = flow { "world!" }
f1() + " " + f2()
} onComplete println
Akka Dataflow 使用 Scala 的Delimited Continuations自动在幕后为您生成延续。
我目前知道的唯一这样的库是Akka DataFlow:http ://doc.akka.io/docs/akka/snapshot/scala/dataflow.html
查看项目定义(https://github.com/akka/akka/blob/master/project/AkkaBuild.scala),akka-dataflow 似乎没有太多依赖关系,所以它应该是相当轻量级的。
更新: 这是一个使用示例,取自 akka-dataflow 的文档:
flow {
val f1 = flow { "Hello" }
val f2 = flow { "world!" }
f1() + " " + f2()
} onComplete println
这清楚地说明了您可以以程序方式编写代码(即使在引擎盖下它确实被转换为 map/flatMap 链)。
作为另一种简单的选择,您是否考虑过仅用于延续?它们使用起来有点冗长,但总体好处是相同的:以程序方式编写代码,而不是使用显式的 cps 样式将其弄乱。举个例子,上面的例子直接翻译成下面的纯scala代码:
{for {
f1 <- future( "Hello" );
f2 <- future( "world!" )
} yield f1 + " " + f2
} onComplete println
这没什么不同。而且你不会找到比没有库更轻量级的库(尽管我承认在简洁性方面我仍然更喜欢 akka-dataflow,但只是略微领先)。
Scala 中还有另外一种数据流并发实现,您可能想要签出,ScalaFLow。github repo 也包含论文 PDF,非常详细地描述了这项工作。
Kai 在这个论坛帖子中给出了一个演示:
引用:
“一个最小的演示(是的,看起来像期货):
val v = new Variable[Int]
flow { println( v() ) // suspends without blocking }
flow { v := 42 // resumes above flow }
"