假设我有 4 个 future 的计算要做。前两个可以并行完成,但第三个必须在前两个之后完成(即使前两个的值未在第三个中使用——将每个计算视为执行某些数据库操作的命令)。最后,在所有前 3 个计算之后必须进行第 4 个计算。此外,还有一个副作用可以在前 3 个完成后开始(将其视为启动周期性可运行)。在代码中,这可能类似于以下内容:
for {
_ <- async1 // not done in parallel with async2 :( is there
_ <- async2 // any way of achieving this cleanly inside of for?
_ <- async3
_ = sideEffect // do I need "=" here??
_ <- async4
} yield ()
这些评论显示了我对代码质量的怀疑:
- 在 for comprehension 中并行执行两个操作的最干净的方法是什么?
- 有没有一种方法可以在没有那么多“_”字符的情况下实现这个结果(也不分配命名引用,至少在 sideEffect 的情况下)
- 执行此操作最干净、最惯用的方法是什么?
最佳答案
您可以使用 zip
组合两个 futures,包括 zip
本身的结果。您最终会得到包含元组的元组,但如果您对 Tuple2
使用中缀表示法,则很容易将它们分开。下面我为简洁定义了一个同义词 ~
(这是解析器组合器库所做的,除了它的 ~
是一个不同的类,其行为类似于 Tuple2
).
作为 _ =
的替代方案,您可以将其移至 yield
中,或使用大括号和分号将其与以下语句组合。我仍然认为 _ =
更符合习惯,至少在 for
中有一个副作用语句是完全符合习惯的。
val ~ = Tuple2
for {
a ~ b ~ c <- async1 zip
async2 zip
async3
d <- { sideEffect; async4 }
} yield (a, b, c, d)
关于scala - 在 Scala 中混契约(Contract)步、异步和并行计算以理解 future 的最惯用方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23860638/