【问题标题】:Scala future for comprehension chain futures and resultsScala 未来的理解链期货和结果
【发布时间】:2019-09-27 15:24:11
【问题描述】:

我想执行 func 方法,每个方法调用都具有前一个结果并返回最终方法值。

有没有办法让它不那么冗长和动态,这样如果我必须这样做 100 多次,我最终不会有 100 行?

    val a : Future[String] = for {
      comp1Result <- Future { func(shopRequest) }
      comp2Result <- Future { func(comp1Result) }
      comp3Result <- Future { func(comp2Result) }
      comp4Result <- Future { func(comp3Result) }
      comp5Result <- Future { func(comp4Result) }
      comp6Result <- Future { func(comp5Result) }
      comp7Result <- Future { func(comp6Result) }
      comp8Result <- Future { func(comp7Result) }
      comp9Result <- Future { func(comp8Result) }
      comp10Result <- Future { func(comp9Result) }
      comp11Result <- Future { func(comp10Result) }
      comp12Result <- Future { func(comp11Result) }
      comp13Result <- Future { func(comp12Result) }
      comp14Result <- Future { func(comp13Result) }
      comp15Result <- Future { func(comp14Result) }
      comp16Result <- Future { func(comp15Result) }
      comp17Result <- Future { func(comp16Result) }
    } yield {comp17Result }

【问题讨论】:

  • 我猜你需要一个带计数器的递归函数,所以它可以在第 17 次调用时停止。

标签: scala asynchronous functional-programming


【解决方案1】:

您可以创建一个简单的尾递归方法,通过flatMap 重复链接Future{ func(result) } 给定次数:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def func(s: String): String = ???

@scala.annotation.tailrec
def loopFutures(future: Future[String], n: Int): Future[String] = n match {
  case 1 => future
  case _ => loopFutures(future.flatMap(r => Future{ func(r) }), n - 1)
}

例如,使用方法loopFutures 来执行你的for-comprehension

loopFutures(Future{ func(shopRequest) }, 17)

【讨论】:

    【解决方案2】:

    Future 中执行每个计算没有意义,在一个Future 中执行所有计算更简单。然后可以使用简单的foldLeft操作:

    Future((1 to 17).foldLeft(shopRequest) { case (r, _) => func(r) })
    

    如果你确实想每次都创建一个Future,它看起来像这样:

    (1 to 17).foldLeft(Future.successful(shopRequest)) {
      case (r, _) => r.flatMap(x => Future(func(x)))
    }
    

    【讨论】:

    • 不错,蒂姆!第二个示例中的 flatMap 可以更改为地图: case (r, _) => r map func
    猜你喜欢
    • 1970-01-01
    • 2015-07-17
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    • 1970-01-01
    相关资源
    最近更新 更多