基本操作

Mapping

您可以通过调用 ZIO#map 方法让 effect 在成功通道上进行映射。这使您可以转换effect 的成功值。

import zio._

val succeeded: UIO[Int] = IO.succeed(21).map(_ * 2)

您可以通过调用  ZIO#mapError 方法让效果在错误通道上进行映射。这使您可以转换 effect 的失败值。

val failed: IO[Exception, Unit] = 
  IO.fail("No no!").mapError(msg => new Exception(msg))

注意,在 effect 的成功或错误通道上进行映射不会更改效果的成功或失败,就如同  Either,在任何一个通道上映射都不会改变它是 Left 还是 Right

链式调用

您可以使用 flatMap 方法串联执行两个 effects,这要求您提供一个回调函数,该回调接收第一个 effect 的输出作为它的输入,最终的返回取决于此第二个 effect 的结果:

val sequenced = 
  getStrLn.flatMap(input => putStrLn(s"You entered: $input"))

如果第一个 effect 失败了,那么传递给 flatMap 的回调将不会被执行,并且 flatMap 返回的合成效果也将失败。

在 任何 的效果链中,第一个失败将会直接导致整个调用链立即终止,就像抛出异常会提早从一系调用中退出一样。

For Comprehensions

因为 ZIO 数据类型同时支持 flatMap 和 map 调用,所以你可以使用 Scala 的 for comprehensions 来构建 effect 的执行序列:

val program = 
  for {
    _    <- putStrLn("Hello! What is your name?")
    name <- getStrLn
    _    <- putStrLn(s"Hello, ${name}, welcome to ZIO!")
  } yield ()

For comprehensions 提供了用于组合效果链的更具过程性的语法。

Zipping

您可以使用 ZIO#zip 方法将讲个 effect 合并成一个单个的 effect,产生的 effect 是一个包含了两个 effect 的成功值的元组:

val zipped: UIO[(String, Int)] = 
  ZIO.succeed("4").zip(ZIO.succeed(2))

要注意 zip 运算的顺序:左边效果的运算先于右边。

在任何一个 zip 运算中,如果左边或右边中的任意一边失败,那么整个effect组合都将失败,因为生成元组需要两个值。

有时候一个成功的 effect 的返回值是无用的(比如 Unit),那么可以使用 ZIO#zipLeft 或 ZIO#zipRight 函数来方便地舍弃,这个些函数先执行 zip,然后执行映射(map)来丢弃一边:

val zipRight1 = 
  putStrLn("What is your name?").zipRight(getStrLn)

zipRight 和 zipLeft 函数分别可以使用符号别名 *> 和 <* 来代替。有些开发者认为以下代码的可读性更高:

val zipRight2 = 
  putStrLn("What is your name?") *>
  getStrLn

Next Step

如果您对ZIO effect 的基本操作感到满意,那么下一步就是学习错误处理.

Leave a Reply
Your email address will not be published.
*
*

BACK TO TOP