gpt4 book ai didi

scala - 如何在 ZIO 中实现不使用潜在大量堆空间的循环

转载 作者:行者123 更新时间:2023-12-04 00:59:56 25 4
gpt4 key购买 nike

我知道ZIO是维护自己的堆栈,即zio.internal.FiberContext#stack ,它保护递归函数,如

def getNameFromUser(askForName: UIO[String]): UIO[String] =
for {
resp <- askForName
name <- if (resp.isEmpty) getNameFromUser(askForName) else ZIO.succeed(resp)
} yield name

从堆栈溢出。但是,它们仍然占用 ZIO 解释器堆栈中的空间,这可能导致 OutOfMemoryError对于非常深的递归。你会如何重写 getNameFromUser从上面的函数,即使在 askForName 时也不炸毁堆效果返回空字符串很长一段时间?

最佳答案

您正在递归函数中使用循环。基本上每次打电话getNameFromUser您正在向堆分配对象,堆永远无法释放这些对象,因为您在 t1 上创建的对象需要在 t2 中创建的对象来解析,但 t2 中的对象需要 t3 上的对象无限解析。

您应该像 forever 一样使用 ZIO 组合器而不是循环或您可以在 Schedule 上找到的任何其他信息

 import zio.Schedule

val getNameFromUser: RIO[Console, String] = for {
_ <- putStrLn("Waht is your name")
name <- zio.console.getStrLn
} yield name

val runUntilNotEmpty = Schedule.doWhile[String](_.isEmpty)

rt.unsafeRun(getNameFromUser.repeat(runUntilNotEmpty))

[编辑] 添加一个不同的例子,因为你真正需要的是:
import zio._
import zio.console._
import scala.io.StdIn

object ConsoleEx extends App {

val getNameFromUser = for {
_ <- putStrLn("What is your name?")
name <- getStrLn
_ <- putStr(s"Hello, $name")
} yield ()

override def run(args: List[String]) =
getNameFromUser.fold(t => {println(t); 1}, _ => 0)

}

但是请注意,我你有 fork in run := true在您的 build.sbt那么你还需要添加 run / connectInput := true如解释 in the sbt docs

关于scala - 如何在 ZIO 中实现不使用潜在大量堆空间的循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59176271/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com