- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个严重的副作用函数(想想数据库调用),我想将其用作惰性值,这样它只会在第一次使用时被调用(如果从未使用过则根本不会被调用)。
我如何使用 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)
}
我想我必须传递一个生成 Int
的 IO
而不是已经具体化的 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
“包装”成使其变得懒惰的东西?
最佳答案
我想到了以下内容:
def lazyIO[E,A](io: IO[E,A]): IO[Nothing, IO[E, A]] = {
for {
barrier <- Promise.make[Nothing, Unit]
fiber <- (barrier.get *> io).fork
} yield barrier.complete(()) *> putStrLn("getting it") *> fiber.join
}
ZIO 1.0-RC4 的更新版本(带有环境支持):
def lazyIO[R, E, A](io: ZIO[R, E, A]): ZIO[R, Nothing, ZIO[R, E, A]] = {
for {
barrier <- Promise.make[Nothing, Unit]
fiber <- (barrier.await *> io).fork
} yield barrier.succeed(()) *> fiber.join
}
所以这是一个接受 IO 并返回它的惰性版本的 IO。
它通过启动一个 fiber
来工作运行原始 io
, 但只有在 Promise ( barrier
) 完成之后。
惰性IO首先完成barrier
(如果它是第一个执行此操作的人,它将解锁 fiber
,后者又运行包装的 io
)然后加入 fiber
检索计算结果。
有了这个,我可以做到
override def run(args: List[String]): IO[Nothing, Main.ExitStatus] = for {
valueFromDb <- lazyIO(longRunningDbAction)
_ <- maybeUseTheValue(valueFromDb)
_ <- maybeNeedItAgain(valueFromDb)
} yield ExitStatus.ExitNow(0)
并且控制台输出显示延迟值确实被拉取了两次,但只有第一个触发了“数据库访问”:
getting it
Calling the database now
The database said 42
getting it
Okay, we need it again here: 42
关于scala - 如何让 Scalaz ZIO 变得懒惰?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53851349/
这可能是一个愚蠢的问题,但从 ZIO 开始,我无法将 Seq[ZIO] 转换为 ZIO[Seq]: def translate(keys: Seq[String], locales: Seq[Loca
我创建了我的服务的两个版本。第一个使用 Futures,另一个使用 ZIO 作为效果。 我有一个使用 Future 作为结果效果的简单方法: def get(id: String)(implicit
我有下一个代码: import zio._ import scala.concurrent.Future case class AppError(description: String) extend
我有下一个代码: import zio._ import scala.concurrent.Future case class AppError(description: String) extend
我有一个返回一些 ZIO 的方法: def method(...): ZIO[Any with clock, SomeError, Unit] 调用此方法返回Task[Unit]: def other
(希望)关于 Scalaz Zio 的简单问题。 我有一些重构为 Zio 的旧代码。我希望该代码的一条路径保持原样: 同步 阻塞 在当前线程上(这是一个硬性要求) 我如何运行 IO这样它的行为就像旧的
我正在使用 ZIO:https://github.com/zio/zio 在我的 build.sbt : "dev.zio" %% "zio" % "1.0.0-RC9" 无论我尝试过什么,每次我需要
我想为 abort-early-in-a-fold 添加一个答案对于ZIO。 所以我采用了猫的解决方案:cats solution def sumEvenNumbers(nums: Stream[In
我有一堆 IO,所有这些都可能成功或失败: val result: Seq[IO[MyFailure, MySuccess]] = ... 我需要总结结果,以便我可以一起检查所有失败和所有成功: ca
我在 Scala 中有一个类有四个参数,其中 2 个是变量,我想在 Zio 中使用 Ref 数据类型来控制对这些变量的访问,这是我的代码: import zio._ class Rectangle(v
我找不到有关如何使用 ZIO 测试忽略套件或测试的任何信息。 无论是在示例中还是在文档中( https://zio.dev/docs/usecases/usecases_testing ) 有一个ig
我知道ZIO是维护自己的堆栈,即zio.internal.FiberContext#stack ,它保护递归函数,如 def getNameFromUser(askForName: UIO[Strin
我想按顺序运行两个集成测试。如何在 ZIO Test 中实现这一点? 这是套房: suite("Undeploy a Package")( testM("There is a Package"
scala.js 是否与 scala ZIO 一起使用? 我想在 scala.js 中使用 scala ZIO 我只知道如何在普通应用程序中使用 scala ZIO 有谁知道如何在 scala.js
我有几个 Booleans我想测试,比如 assert(g8Exists, equalTo(true)) && assert(projectExists, equalTo(true)) && asse
我想在 ZIO Fibers 上使用组合器 orElse。 从文档: 如果第一个纤维成功,则合成的纤维将成功,其结果;否则,组成的光纤将以第二条光纤的退出值完成(无论成功或失败)。 import zi
我有以下 ZIO 程序,其中包含两个永久运行的进程: for { .. numberProvider <- numberProvider(queue).fork //
我试过了 assert(anOption)(contains("x")) 但这仅适用于 Iterables,例如 List 或 Seq。 最佳答案 assert(anOption)(isSome(eq
我有以下功能,我想测试: def people(id: Int): RIO[R, People] 如果有一个人,此函数将返回 id , 分别如果没有,则失败,例如: IO.fail(ServiceEx
我有一个严重的副作用函数(想想数据库调用),我想将其用作惰性值,这样它只会在第一次使用时被调用(如果从未使用过则根本不会被调用)。 我如何使用 ZIO 做到这一点? 如果我的程序看起来像这样,函数只被
我是一名优秀的程序员,十分优秀!