我正在使用ZIO:https://github.com/zio/zio
在我的build.sbt
中:
"dev.zio" %% "zio" % "1.0.0-RC9"
无论我尝试什么,每次需要它们时,都会一直在计算我的结果:
val t = Task {
println(s"Compute")
12
}
val r = unsafeRun(for {
tt1 <- t
tt2 <- t
} yield {
tt1 + tt2
})
println(r)
对于此示例,日志如下所示:
Compute
Compute
24
我尝试过Promise
:
val p = for {
p <- Promise.make[Nothing, Int]
_ <- p.succeed {
println(s"Compute - P")
48
}
r <- p.await
} yield {
r
}
val r = unsafeRun(for {
tt1 <- p
tt2 <- p
} yield {
tt1 + tt2
})
我遇到同样的问题:
Compute - P
Compute - P
96
我尝试过
val p = for {
p <- Promise.make[Nothing, Int]
_ <- p.succeed(48)
r <- p.await
} yield {
println(s"Compute - P")
r
}
首先,我在想也许执行了管道,但没有重新计算值,但我也不工作。
我希望能够异步计算我的值并能够重用它们。 我看着How do I make a Scalaz ZIO lazy?,但它对我也不起作用。
答案 0 :(得分:4)
计算结果是否有副作用?如果不是这样,您可以仅使用常规的旧式val,也许可以将其提升为ZIO
。
lazy val results = computeResults()
val resultsIO = ZIO.succeedLazy(results)
如果确实有副作用,则您将无法真正缓存结果,因为这不会是参照透明的,这是ZIO
的重点。
您可能需要做的是在您的计算flatMap
上Task
,然后在需要调用flatMap
的程序中编写需要该计算结果的其余程序,将{{ 1}}值作为参数通过您的函数调用进行。
result
答案 1 :(得分:3)
ZIO有memoize,它应该基本上可以完成您想要的操作。我暂时没有办法对其进行测试,但它的工作方式应类似于:
for {
memoized <- t.memoize
tt1 <- memoized
tt2 <- memoized
} yield tt1 + tt2
请注意,除非实际代码的第二行和第三行具有某些分支,可能导致Task
永远不会被调用或仅被调用一次,否则产生的答案和副作用与简单得多的相同:
t flatMap {tt => tt + tt}