理解是否有类似“flatYield”的东西?

时间:2014-11-13 16:29:27

标签: scala for-comprehension

我有一些像

这样的代码
//all data have different types
val data1Future = loadData1(params)
val data2Future = loadData2(params)
val data3Future = loadData3(params)

def saveResult(rez): Future[_] = ???

data1Future.flatMap { data1 =>
  data2Future.flatMap { data2 =>
    data3Future.flatMap { data3 =>
      //do some computation
      //several rows and several vals
      val rez = ???
      saveResult(rez)
   }
  }
}

但它有点丑陋:)不幸的是,我不能用于理解,因为我需要像“flatYield”这样的东西

for {
  data1 <- data1Future
  data1 <- data1Future
  data1 <- data1Future
} flatYield {
  //do some computation
  //several rows and several vals
  val rez = data1 + data2 + data3
  saveResult(rez)
}

你知道模式是如此优雅的“理解”,但在链的末尾使用flatMap而不是map?

3 个答案:

答案 0 :(得分:3)

看起来你只想在你理解中想到另一条线,所有这些“其他计算”都应该放在另一个函数中以保持清洁:

for {
  data1 <- data1Future
  data2 <- data2Future
  data3 <- data3Future
  rez <- otherFunction(data1, data2, data3)
} yield rez 

def otherFunction(d1: ?, d2: ?, d3: ?): Future[?] = {
  //do some computation
  //several rows and several vals
}

或者您可以使用以下内容:

(for {
  data1 <- data1Future
  data2 <- data2Future
  data3 <- data3Future
} yield {
  (data1, data2, data3)
}) flatMap { case (data1, data2, data3) =>
  //do some computation
  //several rows and several vals
  saveResult(rez)
}

答案 1 :(得分:3)

你可以这样做:

for {
  data1 <- data1Future
  data2 <- data2Future
  data3 <- data3Future
  rez = {
    //do some computation
    //several rows and several vals
    data1 + data2 + data3
  }
  r <- saveResult(rez)
} yield r

这转换为

data1Future.flatMap { data1 =>
  data2Future.flatMap { data2 =>
    data3Future.flatMap { data3 =>
      val rez = {
        //do some computation
        //several rows and several vals
        data1 + data2 + data3
      }
      saveResult(rez).map(r => r)
    }
  }
}

与您的代码同构。

答案 2 :(得分:0)

使用for comprehension(就像你声明的目标一样)相当于定义flatMap操作序列中的future将等到每个未来的结果然后转到下一个。由于你的期货不依赖于彼此,你可以在不等待前一个完成的情况下启动它们 - 这就是你在最初的例子中所做的。

同时启动它们并将期货存储在序列中使用Future.sequence将期货集合转换为单个Future,直到所有期货完成(或其中任何一个失败)才能完成。然后在将来完成时保存您的结果。

val data1Future = loadData1(params) //type = Future[foo]
val data2Future = loadData2(params)
val data3Future = loadData3(params)

val listOfFutures = List(data1Future,data2Future,data3Future) //type = List[Future[foo]]

val futureOfList = Future.sequence(listOfFutures)  //type = Future[List[foo]]

futureOfList.onComplete( list => saveResult(list.reduce(_ + _))