2

Why putStrLn in flatMap followed by a result statement didn't get effectively write to stdout?

object Mgr extends App {

  def main1(args: Array[String]) = getStrLn.flatMap { s =>
    putStrLn(s)  // Why this did not write to console?
     UIO.succeed(s)
  }

  override def run(args: List[String]): URIO[zio.ZEnv, Int] = main1(Array()).fold(_ => 1,
    { x =>
       println(x)  // only this line wrote to console, why?
      0
    })
}
4

1 回答 1

8

您的问题基本上是,您将两个效果放入单个 flatMap 中。

通过调用putStrLn(s)您实际上并没有打印到控制台,您只是创建了在解释和运行程序时(run调用方法时)将打印的操作的描述。并且因为在您的平面图中仅返回最后一个值(在您的情况下UIO.succeed(s)),所以在构建 ZIO 程序时只会考虑它。

您可以通过链接这两个操作来修复您的程序。

您可以使用*>操作员来做到这一点:

def main1(args: Array[String]) = getStrLn.flatMap { s =>
    putStrLn(s)  *>  UIO.succeed(s)
}

或者您可以将效果放入单独的平面地图中。但是由于您想创建副作用(通过打印值),但随后将值进一步不变地传递,您需要使用特殊功能tap

def main1(args: Array[String]) = getStrLn.tap { s =>
    putStrLn(s)
}.flatMap { s =>
    UIO.succeed(s)
}

这篇很棒的文章(查看第一点)也描述了您的问题(还有其他陷阱)。

于 2020-04-05T07:28:15.900 回答