当前位置: 首页 > 知识库问答 >
问题:

Scala对未来的“理解”

那开济
2023-03-14

我正在阅读Scala Cookbook(http://shop.oreilly.com/product/0636920026914.do)

有一个与未来使用相关的例子,涉及理解。

到目前为止,我对理解的理解是,当与一个集合一起使用时,它会产生另一个相同类型的集合。例如,如果每个< code>futureX的类型为< code>Future[Int],则以下内容也应为< code>Future[Int]类型:

for {
   r1 <- future1
   r2 <- future2
   r3 <- future3
} yield (r1+r2+r3)

有人能解释一下使用时到底发生了什么吗


共有3个答案

曾歌者
2023-03-14

如果可能的话,它允许r1r2r3并行运行。这可能是不可能的,这取决于有多少线程可用于执行未来的计算,但通过使用此语法,您可以告诉编译器在可能的情况下并行运行这些计算,然后在所有计算完成后执行yield()

甘西岭
2023-03-14

在这里详细阐述这些现有答案,一个简单的结果来演示理解是如何工作的

它的功能有点长,但它们值得研究。

一个函数,它给我们一个整数范围

scala> def createIntegers = Future{
             println("INT "+ Thread.currentThread().getName+" Begin.")
             val returnValue = List.range(1, 256)
             println("INT "+ Thread.currentThread().getName+" End.")
             returnValue
         }
createIntegers: createIntegers: scala.concurrent.Future[List[Int]]

给我们一系列字符的函数

scala> def createAsciiChars = Future{
             println("CHAR "+ Thread.currentThread().getName+" Begin.")
             val returnValue = new ListBuffer[Char]
             for (i <- 1 to 256){
                  returnValue += i.toChar
             }
             println("CHAR "+ Thread.currentThread().getName+" End.")
             returnValue
          }
createAsciiChars: scala.concurrent.Future[scala.collection.mutable.ListBuffer[Char]]

为了便于理解,在中使用这些函数调用。

scala> val result = for{
                        i <- createIntegers
                        s <- createAsciiChars
                    } yield i.zip(s)
       Await.result(result, Duration.Inf)
result: scala.concurrent.Future[List[(Int, Char)]] = Future(<not completed>)

对于下面的这些行,我们可以确定所有的函数调用都是同步的,也就是说,在< code>createIntegers完成其执行之前,不会执行< code>createAsciiChars函数调用。

scala> INT scala-execution-context-global-27 Begin.
       INT scala-execution-context-global-27 End.
       CHAR scala-execution-context-global-28 Begin.
       CHAR scala-execution-context-global-28 End.

在< code>for理解之外调用这些函数< code > createscichars 、< code>createIntegers将是异步执行。

司徒兴思
2023-03-14

首先是理解。在SO上回答了很多很多次,它是对几个一元操作的抽象mapflatMapwithFilter。当您使用

r

它看起来像一个命令式计算(monad是关于什么的),您将计算结果绑定到r产量部分被解压缩到map调用中。结果类型取决于monad的类型。

< code>Future trait有一个< code>flatMap和< code>map函数,所以我们可以用它来理解。在你的例子中可以解糖成下面的代码:

future1.flatMap(r1 => future2.flatMap(r2 => future3.map(r3 => r1 + r2 + r3) ) )

不言而喻,如果未来2的执行取决于r1,则无法避免顺序执行,但如果未来的计算是独立的,则有两种选择。您可以强制顺序执行,也可以允许并行执行。您不能强制后者,因为执行上下文将处理此问题。

val res = for {
   r1 <- computationReturningFuture1(...)
   r2 <- computationReturningFuture2(...)
   r3 <- computationReturningFuture3(...)
} yield (r1+r2+r3)

将始终按顺序运行。它可以很容易地用去加法来解释,之后后续的计算返回未来X调用仅在平面图内部调用,即。

computationReturningFuture1(...).flatMap(r1 => 
    computationReturningFuture2(...).flatMap(r2 => 
        computationReturningFuture3(...).map(r3 => r1 + r2 + r3) ) )

但是,这能够并行运行,并且用于理解聚合结果:

val future1 = computationReturningFuture1(...)
val future2 = computationReturningFuture2(...)
val future3 = computationReturningFuture3(...)

val res = for {
   r1 <- future1
   r2 <- future2
   r3 <- future3
} yield (r1+r2+r3)
 类似资料:
  • 我想在我的play scala Web应用程序中进行错误处理。 我的应用程序与数据库对话以获取一些行,它遵循以下流程。 < li >首先调用数据库以获取一些数据 < li >使用第一次调用中的数据从数据库中提取其他数据 < li >使用从最近两次db调用中收到的数据形成响应。 下面是我的伪代码。 以上理解中的每一个方法都返回一个未来,这些方法的签名如下。 在以下情况下,我该如何进行错误/故障处理

  • 任务是实现递归方法,返回 Future 并且由于这一部分("在其他递归(结果::: res,尝试1)")代码失败与错误,因为它期望未来[Seq[结果]],但实际上返回未来[对象]。 据我所知,问题在于yield块内的表达式必须返回Seq[Result],以便将来由Monad进行后续包装。但是“递归(结果::res,尝试1)”将返回未来。因此,不是预期的Seq[Result]收益率,而是包含未来的[

  • 我有两个函数返回期货。我正试图使用for-yield理解将第一个函数的修改结果输入到另一个函数中。 此方法有效: 然而,我对“如果”在那里不满意,似乎我应该能够使用地图。 但是当我尝试使用地图时: 我得到一个编译错误: 我尝试了一些变化,但没有发现任何有吸引力的工作。有人能提出更好的理解和/或解释我的第二个例子的错误吗? 下面是一个最小但完整的Scala 2.10可运行示例:

  • 是否有可能“反转”Scala的未来? 有时候,未来成功的结果意味着错误。在这种情况下,翻转一个未来会很好,即调用一个返回未来的函数,如果最初的未来失败,则该函数以指定的值成功,如果最初的未来成功,则以指定的错误失败。

  • 我有一些函数返回带有未来的元组元素列表(Int, Int)。为简单起见,我将定义两个未来 我想用下面的标准过滤并获取这两个未来列表中的元素。 在第二个位置包含相同元素的元组 在此方案中,输出应为 我可以用普通的列表(没有未来)来做这件事,比如下面的理解 如何与期货一起做?

  • Scala使用什么模式来处理这种情况: 你有很多未来(它们可以是任何东西,但为了举例…) 你有一个返回未来的函数 我想做这样的事情: 我想返回一个值,但是我在rent语句中调用foF,我会得到一个