我有一个很重的副作用函数(想想数据库调用),我想将它用作一个惰性值,以便它仅在第一次使用时被调用(如果从未使用过则根本不会调用)。
我如何用 ZIO 做到这一点?
如果我的程序看起来像这样,则该函数只被调用一次(但甚至根本不使用结果):
import scalaz.zio.IO
import scalaz.zio.console._
object Main extends scalaz.zio.App {
def longRunningDbAction: IO[Nothing, Integer] = for {
_ <- putStrLn("Calling the database now")
} yield 42
def maybeUseTheValue(x: Integer): IO[Nothing, Unit] = for {
_ <- putStrLn(s"The database said ${x}")
} yield ()
def maybeNeedItAgain(x: Integer): IO[Nothing, Unit] = for {
_ <- putStrLn("Okay, we did not need it again here.")
} yield ()
override def run(args: List[String]): IO[Nothing, Main.ExitStatus] = for {
valueFromDb <- longRunningDbAction
_ <- maybeUseTheValue(valueFromDb)
_ <- maybeNeedItAgain(valueFromDb)
} yield ExitStatus.ExitNow(0)
}
我想我必须传递一个IO
产生的Int
而不是已经物化的Int
,但是如果我传入只调用数据库的原始IO
文件,它将被重复调用:
object Main extends scalaz.zio.App {
def longRunningDbAction: IO[Nothing, Integer] = for {
_ <- putStrLn("Calling the database now")
} yield 42
def maybeUseTheValue(x: IO[Nothing, Integer]): IO[Nothing, Unit] = for {
gettingItNow <- x
_ <- putStrLn(s"The database said ${gettingItNow}")
} yield ()
def maybeNeedItAgain(x: IO[Nothing, Integer]): IO[Nothing, Unit] = for {
gettingItNow <- x
_ <- putStrLn(s"Okay, we need it again here: ${gettingItNow}")
} yield ()
override def run(args: List[String]): IO[Nothing, Main.ExitStatus] = for {
_ <- maybeUseTheValue(longRunningDbAction)
_ <- maybeNeedItAgain(longRunningDbAction)
} yield ExitStatus.ExitNow(0)
}
有没有办法将它“包装”longRunningDbAction
成让它变得懒惰的东西?