2.2 zio入门——按顺序组合ZIO

2.2 按顺序组合ZIO

正如上小节所述,ZIO效果是描述并发工作流的蓝图,并且我们通过转换和组合更小,更简单的效果来构建更复杂的效果,从而解决业务问题。

我们看到了如何使用 ZIO 的 delay 运算符将一个效果转换为另一种效果,并将其执行延迟到将来。 除了延迟之外,ZIO还拥有数十种其他强大的运算符,它们可以转换并组合效果以解决现代应用程序开发中的常见问题。

我们将在随后的章节中学习大多数这些运算符,但是我们需要介绍的最重要的运算符之一就是flatMap。ZIO效果的flatMap方法表示两个效果的顺序组合,使我们可以根据第一个效果的输出来创建第二个效果。

flatMap的简化类型签名如下所示:

trait ZIO[R, E, A] { ...
	def flatMap[B](andThen: A => ZIO[R, E, B]): ZIO[R, E, B] = ... ...
}

实际上,flatMap的意思是说:“先运行第一个效果,然后根据第一个运行的结果运行第二个效果”。 使用此顺序运算符,我们可以描述一个简单的工作流,该工作流读取用户输入,然后将输入显示给用户,如以下代码片段所示:

// 下面的程序将两个没有关系的effect通过flatMap串成一个effect
import scala.io.StdIn 
val readLine = ZIO.effect(StdIn.readLine()) 
def printLine(line: String) =ZIO.effect(println(line)) 
val echo = readLine.flatMap(line => printLine(line))

请注意,我们在控制台上打印的内容取决于我们从控制台读取的内容:因此,我们依次执行两件事,而我们所做的第二件事取决于我们所做的第一件事所产生的结果。

flatMap基本的运算符,因为它捕获了在程序中语句的执行方式:后面的语句取决于前面的语句计算的结果。

如果我们通过过程式的代码编写这段程序就是:

val line = Console.readLine Console.println(line)

过程编程与flatMap运算符之间的这种关系是如此精确,我们实际上可以通过将每个简单的语句包装在诸如ZIO.effect之类的构造函数中,然后使用flatMap将这些语句粘合在一起,从而将任何程序程序转换为ZIO。

例如,假设我们在以下代码段中显示了程序程序:

  val data = doQuery(query)
  val response = generateResponse(data) writeResponse(response)

我们可以将上面的代码转变为下面的形式:

  ZIO
    .effect(doQuery(query))
    .flatMap(
      data =>
        ZIO
          .effect(generateResponse(data))
          .flatMap(response => ZIO.effect(writeResponse(response)))
    )

尽管是一种简单的转换,但是如果连续超过两个或三个flatMap操作,代码的嵌套将变得有些困难。 幸运的是,Scala具有for推导的功能,该功能使我们能够以类似于过程编程的方式表达顺序组合。
在下一节中,我们将详细探讨各种理解。

2.2.1

通过 for 推导,我们可以将下面的代码:

readLine.flatMap(line => printLine(line))

重写成下面的形式:

  import zio._
  val echo = for {
    line <- readLine
    _ <- printLine(line) } yield ()
  }

从这个简短的代码片段中可以看出,没有嵌套,并且理解中的每一行看起来都类似于过程编程中的一条语句。

for推导具有如下的结构:

  • 它们由关键字for引入,后跟一个代码块,并以关键字yield结束,关键字yield之后是单个参数,代表effect的执行成功的返回值。
  • for 推导的每一行都使用格式 result <-effect 编写,其中effect是一个作用,而result是一个变量,代表该作用的成功值。 如果不需要作用的结果,则可以将下划线用作变量名称。

Scala将具有n行的for推导转换为对效果的flatMap方法的n-1次调用,最后对最后一个作用调用map方法。

例如:

  for {
    x <- doA
    y <- doB(x)
    z <- doC(x, y)
  } yield x + y + z

scala程序会将上面的代码转为下面的语句

  doA.flatMap(x => doB(x).flatMap(y => doC(x, y).map(z => x + y + z)))

许多Scala开发人员发现,for推导比起一连串的FlatMap嵌套调用更容易理解。 在本书中,除了非常简短的摘录外,我们更喜欢for推导而不是显式调用flatMap。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值