2.1 zio入门——把函数作用作为工作蓝图

编程入门 行业动态 更新时间:2024-10-28 14:37:18

2.1 zio入门——把函数作用作为工作<a href=https://www.elefans.com/category/jswz/34/1768489.html style=蓝图"/>

2.1 zio入门——把函数作用作为工作蓝图

ZIO标准库的核心数据类型是ZIO[R, E, A],这种类型的值被称为函数式作用

函数式作用是并发工作流的一种蓝图,如图1所示。该蓝图本质上是纯描述性的,必须执行才能观察到任何副作用,例如与数据库的交互,日志记录,流传输 网络中的数据,或接受请求。

ZIO [R,E,A]类型的函数式作用要求您在运行的时候提供R类型的值,并且在执行效果时,它可能会执行失败返回类型为E(错误类型),或者执行成功返回类型为A(成功类型)。

稍后我们将详细讨论这些类型参数。但是首先,我们需要了解将效果变为蓝图意味着什么。
在传统的过程编程中,我们习惯于代码的每一行直接与外界交互。例如,考虑以下代码片段:

val goShopping: Unit = {
println("Going to the grocery store")
}

scala程序一旦运行goShopping变量,就会立刻输出 Going to the grocery store. 这种风格的编程方式是过程式编程。基本上所有程序员都熟悉这种编程方式,因为大多数编程语言天生就是过程式的。
对于简单的程序而言,过程式编程是非常方便的。但是当我们这样写程序的时候,我们想要做的事情(去商店)与我们想要做的事情(现在去商店)纠缠不清。这种纠缠可能导致许多难以理解和测试的样板代码,难以更改,并且充满了直到生产才发现的细微错误。
例如,假设我们实际上不想现在去杂货店,而是从现在开始一个小时。我们可能会这样去编写代码:

ScheduledExecutorService:import java.util.concurrent.{ Executors, ScheduledExecutorService } 
import java.util.concurrent.TimeUnit._val scheduler: ScheduledExecutorService = Executors.newScheduledThreadPool(1)scheduler.schedule(new Runnable { def run: Unit = goShopping }, 1,HOURS
) scheduler.shutdown()

在这段程序中我们创建了一个executor,在一小时后执行我们的 goShopping 操作。然后在程序执行完之后 shut down 调度器。
该解决方案不仅涉及难以理解,测试和难以更改的样板代码,而且还存在一个细微的错误!
因为goShopping是直接执行的,而不是工作计划,所以一旦JVM加载 goShopping,就会将 “Going to the grocery store”打印到控制台。因此,我们现在要去杂货店,而不是现在的一个小时!

实际上,我们计划在一小时内执行的唯一操作就是返回goShopping的Unit值,这根本不需要执行任何操作。

在这种情况下,我们可以通过将goShopping定义为def而不是val来推迟其计算,从而解决问题。但是这种方法脆弱且容易出错,迫使我们仔细考虑何时对程序中的每个语句进行求值,而不再是语句的顺序。

我们还必须注意不要过早计算。我们可能将其赋值或放入数据结构中,这可能会导致过早计算。好像我们谈购物一样,但是一旦提到“食品”一词,它们就已经在门口了!实际上我们只是打算去购买而已。

解决此问题(以及并发编程中的大多数问题)的方法是在程序值中创建描述我们想要做什么的语句。这样,我们就可以将我们想做的事情与想怎么去做这件事情分开。

下面这段代码展示了怎么用zio编写这段程序:

import zio._
val goShopping = ZIO.effect(println("Going to the grocery store"))

在这段程序中我们用 effect 的构造函数创建了一个 goShopping 的函数式作用。这个 effect 只是描述了我们要去超时,但是事实上没有立刻做任何事。这主要是因为 effect 的参数是 effect :=> A, 这是 () => A 的简写。可以在 scala REPL中测试这段代码,你并不会得到任何输出。

为了去超市,我们必须运行这个执行和定义分开的作用。从而使我们可以消除上面提到的问题,并极大地简化代码。

通过这种定义 go shopping的方式,我们现在可以阐述 在怎么把 ”how“ 和 “what” 分开,然后通过组合作用的方式解决复杂业务问题。

下面的示例通过 ZIO类型的静态方法 delay ,将 goShopping函数转换为一个一小时后执行的副作用。

import zio.clock._ 
import zio.duration._
val goShoppingLater = goShopping.delay(1.hour)

得益于可以将工作流描述为普通的不可变值功能,我们不必担心怎么去定义goShopping又或者过早的运行他。同样,delay 运算符返回的值只是另一个effect,因此我们可以轻松地使用它以相同的方式构建更复杂的程序。

在ZIO中,每个ZIO效果都只是一种描述-并发工作流程的蓝图。在编写程序时,我们创建了更大,更复杂的蓝图,这些蓝图更接近于解决业务问题。当我们完成并具有描述我们需要做的所有事情的效果时,我们将其交给ZIO runtime,ZIO runtime将执行该蓝图并产生程序结果。

那么我们如何实际运行ZIO效果?最简单的方法是扩展App特性并实现run方法,如以下代码片段所示:

import zio._
object GroceryStore extends App { def run(args: List[String]) = goShopping.exitCode 
}

run函数要求我们返回一个ExitCode,该退出代码描述了进程终止时要使用的退出值。 在上定义的exitCode方法是一种方便的方法,可将所有成功都转换为ExitCode(0),将所有失败转换为ExitCode(1)。

更多推荐

2.1 zio入门——把函数作用作为工作蓝图

本文发布于:2023-07-03 16:27:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1008945.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:蓝图   函数   入门   作用   工作

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!