ZIO:如何只计算一次?

Won*_*nay 4 functional-programming scala zio

我正在使用 ZIO: https: //github.com/zio/zio

在我的build.sbt

"dev.zio" %% "zio" % "1.0.0-RC9"
Run Code Online (Sandbox Code Playgroud)

无论我尝试什么,每次需要时都会计算我的结果:

val t = Task {
  println(s"Compute")
  12
}

    val r = unsafeRun(for {
      tt1 <- t
      tt2 <- t
    } yield {
      tt1 + tt2
    })

    println(r)
Run Code Online (Sandbox Code Playgroud)

对于此示例,日志如下所示:

Compute
Compute
24
Run Code Online (Sandbox Code Playgroud)

我尝试过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
    })
Run Code Online (Sandbox Code Playgroud)

我也遇到同样的问题:

Compute - P
Compute - P
96
Run Code Online (Sandbox Code Playgroud)

我尝试过

    val p = for {
      p <- Promise.make[Nothing, Int]
      _ <- p.succeed(48)
      r <- p.await
    } yield {
      println(s"Compute - P")
      r
    }
Run Code Online (Sandbox Code Playgroud)

首先,我想也许管道被执行了,但没有重新计算的值,但我也不工作。

我希望能够异步计算我的值并能够重用它们。我查看了如何让 Scalaz ZIO 变懒?但它对我也不起作用。

Kar*_*ldt 7

ZIO 有memoize,它基本上应该做你想做的事情。我现在没有办法测试它,但它应该像这样工作:

for {
  memoized <- t.memoize
  tt1 <- memoized
  tt2 <- memoized
} yield tt1 + tt2
Run Code Online (Sandbox Code Playgroud)

请注意,除非实际代码的第二行和第三行有一些分支,可能会导致Task永远不会被调用,或者仅被调用一次,否则会产生与更简单的相同的答案和副作用:

t flatMap {tt => tt + tt}
Run Code Online (Sandbox Code Playgroud)