另一个 scala Futures 组合益智游戏

Another scala Futures composition puzzler

我正在将代码从同步样式迁移到异步样式。问题相当简单:调用一系列函数,然后停止第一个函数以 return 一个非错误结果(returning 该值,否则是最后一个计算值)。我开始于:

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)
  }
}

但是,如果函数变为异步(即 return 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())
}

效果很好,但它会评估所有函数,而不管 return 值如何。但是像:

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))
      }
   }
}

不进行类型检查。有什么建议么?我们可以假设函数的每次调用都是昂贵的,因此 none 应该被调用两次,也不应在序列中的第一个 'successful' 调用之后调用。 TIA

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

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

顺便说一句,如果你想 运行 它们全部 return 以先完成的为准,忽略所有其余部分,那么问题就有点不同了(见 ),但你说每个函数调用都很昂贵,所以我怀疑这就是你想要做的。