那就是说,我在理解中找到了一个漏洞。假设我们有一个功能:
def foo: Future[C] = {
val f: Future[A] = ...
val g: A => Future[B] = ... // DB access maybe. Don't care about return type.
val h: A => Future[C] = ...
// Monads are great.
f.flatMap { a =>
g(a) // Eval time? Return type?
h(a)
}
}
问题
foo
和h
不依赖g
的返回值。即使g
没有,他们也会完成吗?也就是说,如果foo.map(...)
尚未完成,h(a)
会产生g
的值吗?g
的返回类型是什么?它被处理为Unit
,因为它被忽略了吗?答案 0 :(得分:4)
g
的返回类型清楚地表示为Future[B]
,这并没有改变。你是正确的认识到这个价值被抛弃了。在未来[B]中进行的副作用仍然会发生,无论h
创造的未来发生什么,它们都会发生。
我要做的是,为了强调这一点,就是以一种计算上相同的方式来编写它,但更清楚地表明这些事情正在发生:
f.foreach(g)
f.flatMap(h)
每当你看到foreach
它应该触发"必须发生副作用",这对读者来说是一个重要的事情。
答案 1 :(得分:3)
我投了Stew的答案但是会补充一点,如果你关心g
失败了,那么另一种写作方式是:
f.flatMap{
val ga = g(a)
val ha = h(a)
for{
_ <- ga
out <- ha
} yield out
}
这将在不同的主题中运行h
和g
,而不会跳过h
,但会保留g
的错误。