如果我用于理解内是否有平坦的返回值等效

时间:2018-09-17 19:49:28

标签: scala

在以下两个函数中,someF1将不编译,而someF2将编译。这是因为预期someF1将返回Future[Int],但由于我在Future[Future[Int]]中使用了for,所以它返回了for。我不会在someF2中遇到问题,因为我正在Future[Future[]]中将someF2展平。如果我使用嵌入式forsomeF1for的错误用例,并且我应该仅使用它并行执行Futures不按顺序?

  // Start writing your ScalaFiddle code here
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def someF1:Future[Int] = {
  val f1 = Future[Int]{1}

  for(i<-f1) yield{
    if(i == 0) {
      val f2 = Future{2}
      for(j<-f2) yield {i+j} //this will make function return Future[Future[Int]]
    }
    else {
      val f3 = Future{3}
      for(k<-f3) yield {i+k}//this will make function return Future[Future[Int]]
    }
  }
}

// Start writing your ScalaFiddle code here
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def someF2:Future[Int] = {
  val f1 = Future[Int]{1}

  f1.flatMap{i=> //flatMap will flatten Future[Future[Int]]
    if(i == 0) {
      val f2 = Future{2}
      f2.map(j=> {i+j})
    }
    else {
      val f3 = Future{3}
      f3.map(k=>{i+k})
    }
  }
}

2 个答案:

答案 0 :(得分:2)

规则是,通过理解for,最终生成器(即<-)将转换为map()调用。每个其他生成器都是一个flatMap()调用。因此,不,使用嵌套的for后,您将无法实现自己的目标。这样会产生过多的map()个呼叫,而不会产生flatMap()个呼叫。

这将起作用:

def someF1:Future[Int] = {
  val f1 = Future[Int]{1}

  for {
    i <- f1
    j <- Future(2)
    k <- Future(3)
  } yield {
    if (i == 0) i+j
    else        i+k
  }
}

但是在这种情况下,您发射的Future比实际需要的多。

答案 1 :(得分:1)

补充@jwvh的答案

您仍然可以使用以下更复杂的代码段来避免第二次以后的评估:

def someF1:Future[Int] =
  for {
    i <- Future[Int]{1}
    r <- if (i == 0) {
        for (j <- Future[Int]{2}) yield i + j
      } else {
        for (k <- Future[Int]{3}) yield i + k
      }
  } yield r

此外,我建议您看看documentation of for/yield