如何斯卡拉期货与flatMap链接在一起?(How are Scala Futures chaine

2019-08-07 06:27发布

我正在使用期货在斯卡拉第一次和我通过使用flatMap组合子的例子工作; 我一直在关注这个讨论:

http://docs.scala-lang.org/overviews/core/futures.html

具体地,这个例子中:

val usdQuote = future { connection.getCurrentValue(USD) }
val chfQuote = future { connection.getCurrentValue(CHF) }
val purchase = for {
    usd <- usdQuote
    chf <- chfQuote
      if isProfitable(usd, chf)
} yield connection.buy(amount, chf)

purchase onSuccess {
    case _ => println("Purchased " + amount + " CHF")
}

被翻译成这样:

val purchase = usdQuote flatMap {
    usd =>
         chfQuote
        .withFilter(chf => isProfitable(usd, chf))
        .map(chf => connection.buy(amount, chf))
}

我有一点麻烦把握的是如何,这是flatMap执行时?

据我所知,usdQuote和chfQuote由“某些线程”在“一段时间内”执行,并要求他们注册的回调函数,问题是:

a)是否usdQuote和chfQuote同时执行? (我敢肯定,他们是)。

B)如何flatMap分配未来useQuote对美元的价值? 如,是否得到操作usdQuote完成时叫什么名字?

C)什么的线程执行“flatMap”和“地图”操作(可能更多的是后续的从最后一个问题)。

干杯。

Answer 1:

  • a)如果你创建了它们,你已经开始对它们的范围内隐的ExecutionContext执行,所以它取决于如何正在执行他们他们可能同时运行。

  • B)它并没有真正分配值本身,而是在实现使用的onComplete方法来引起你传递给被触发,一旦结果已经达到的功能。 在目前这个时间应该链接到flatMap方法我指的是: https://github.com/scala/scala/blob/v2.11.2/src/library/scala/concurrent/Future.scala#L246

  • C)这些都是通过执行上下文运行前面提到的,也可考虑,如果这些未来的情况下,可以在不同的ExecutionContexts运行,所以换理解的部分可以在不同的线程池来运行。



Answer 2:

我面临着同样的问题...我发现有用此有关,comprehesion一般解释。 可能这会有所帮助:

对于-悟

一种-理解是句法糖 mapflatMapfilter操作的集合。

一般形式是for (s) yield e

  • s是发电机和过滤器的一个序列
  • p <- e是发电机
  • if f是一个过滤器
  • 如果有多个发电机(嵌套循环的等价物),最后产生变化比第一快
  • 您可以使用{ s }代替( s )如果你想使用多条线路,而无需分号
  • e是所得集合的元素

实施例1:

  // list all combinations of numbers x and y where x is drawn from
  // 1 to M and y is drawn from 1 to N
  for (x <- 1 to M; y <- 1 to N)
    yield (x,y)

相当于

(1 to M) flatMap (x => (1 to N) map (y => (x, y)))

转换规则

一种表达式看起来像一个传统的for循环,但工程内部不同

  • for (x <- e1) yield e2被转换为e1.map(x => e2)
  • for (x <- e1 if f) yield e2被转换为for (x <- e1.filter(x => f)) yield e2
  • for (x <- e1; y <- e2) yield e3被转换to e1.flatMap(x => for (y <- e2) yield e3)

这意味着你可以使用for-修真自己的类型,只要你定义地图,flatMap和过滤器

实施例2:

for {  
  i <- 1 until n  
  j <- 1 until i  
  if isPrime(i + j)  
} yield (i, j)

相当于

for (i <- 1 until n; j <- 1 until i if isPrime(i + j))
    yield (i, j)

相当于

(1 until n).flatMap(i => (1 until i).filter(j => isPrime(i + j)).map(j => (i, j)))


Answer 3:

你也有并发的一个很好的例子Future在“执行Scala的笔记-期货- 3(组合程序和异步) ”从阿伦马尼万南

我们的Futures需要并行运行。
为了实现这一目标,我们需要做的是提取Future出块,并分别申报。

码:

val oneFuture: Future[Int] = Future {
  Thread.sleep(1000)
  1
}

val twoFuture: Future[Int] = Future {
  Thread.sleep(2000)
  2
}

val threeFuture: Future[Int] = Future {
  Thread.sleep(3000)
  3
}

换理解

def sumOfThreeNumbersParallelMapForComprehension(): Future[Int] = for {  
    oneValue <- oneFuture
    twoValue <- twoFuture
    threeValue <- threeFuture
} yield oneValue + twoValue + threeValue

flatmap:

def sumOfThreeNumbersParallelMap(): Future[Int] = oneFuture.flatMap { oneValue =>  
    twoFuture.flatMap { twoValue =>
      threeFuture.map { threeValue =>
        oneValue + twoValue + threeValue
      }
    }
}

测试:

describe("Futures that are executed in parallel") {
  it("could be composed using for comprehensions") {
    val futureCombinators = new FutureCombinators
    val result = timed(Await.result(futureCombinators.sumOfThreeNumbersParallel(), 4 seconds))
      result shouldBe 6
  }
}

它说明:

  1. Future是某种类型的值(S)的容器(即,它接受一个类型作为参数并不能没有它存在)。
    你可以有一个Future[Int]Future[String]Future[AwesomeClass] -你不能只是一个普通的Future
    这方面的一个花哨术语的类型构造
    为了比较,一个List是一类的构造函数(和单子也一样)。
    List是那些类型的值的容器Int, String或任何其他类型的。 一个List / Future没有包含的类型不存在。
  2. FutureflatMapunit的功能(和必然一个map功能太)。


文章来源: How are Scala Futures chained together with flatMap?