另一个斯卡拉期货组成的益智游戏

时间:2016-09-11 20:40:41

标签: scala concurrent.futures

我正在将代码从同步样式迁移到异步样式。问题非常简单:调用一系列函数,并使用第一个函数停止返回非错误结果(返回该值,否则返回最后一个计算值)。我开始时:

def find(fs: Seq[Function0[Int]], result: Int = -1): Int = {
  if (fs.isEmpty) result
  else {
    val res = fs.head()
    if (res != 0) res
    else find(fs.tail, res)
  }
}

但是,如果函数变为异步(即返回Future [Int]),我无法获得正确的调用。例如,

def ffind(ffs: Seq[Function0[Future[Int]]], result: Future[Int] = Future { -1 }): Future[Int] = {
  if (ffs.isEmpty) result
  else ffind(ffs.tail, ffs.head())
}

效果很好,但无论返回值如何,它都会评估所有函数。但是类似的东西:

def findBad(ffs: Seq[Function0[Future[Int]]], result: Future[Int] = Future { -1 }): Future[Int] = {
  if (ffs.isEmpty) result
  else {
      ffs.head() map { res =>
        if (res != 0) res
        else findBad(ffs.tail, Future(res))
      }
   }
}

不进行类型检查。有什么建议?我们可以假设一个函数的每个调用都很昂贵,所以没有一个函数应该调用两次,也不应该在第一个函数调用之后调用。按顺序打电话。 TIA

1 个答案:

答案 0 :(得分:1)

这就是为什么它不进行类型检查:findBad会返回Future[Int],但会将res映射到findBad的调用中在Future[Future[Int]]中。您需要将map更改为flatMap。请注意,现在您还需要将res从第一个条件(如果res!= 0)包装到Future中,以便两个分支都返回Future。这是代码:

ffs.head() flatMap { res =>
  if (res != 0) Future.succesful(res)
  else findBad(ffs.tail, Future(res))
}

BTW如果你想要全部运行它们并返回先完成的任何一个,忽略所有其余的,那么它有点不同的问题(参见here),但是你说每个函数调用都很昂贵所以我怀疑你正在做什么。