【问题标题】:Scala flatMap'd Future behaviourScala flatMap 的未来行为
【发布时间】:2015-10-29 01:48:44
【问题描述】:

在某种程度上,期货似乎是真的。他们在简单易用的情况下轻视了多线程,拥抱它们让我更喜欢 Scala 编码。

也就是说,我发现自己的理解存在漏洞。假设我们有一个函数:

def foo: Future[C] = {
  val f: Future[A] = ...
  val g: A => Future[B] = ...  // DB access maybe. Don't care about return type.
  val h: A => Future[C] = ...

  // Monads are great.
  f.flatMap { a =>
    g(a)  // Eval time? Return type?
    h(a)
  } 
}

问题

  1. fooh 不依赖于 g 的返回值。即使g 没有完成,他们会完成吗?也就是说,如果g 还没有完成,foo.map(...) 会产生h(a) 的值吗?
  2. 这里g的返回类型是什么?它被处理为Unit,因为它被忽略了吗?

【问题讨论】:

    标签: scala future


    【解决方案1】:

    g 的返回类型明确表示为Future[B],这不会改变。您正确地认识到这个值被丢弃了。在 Future[B] 中执行的副作用仍然会发生,并且无论 h 创建的未来发生什么,它们都会发生。

    为了强调这一点,我要做的就是以一种计算上等效的方式来编写它,但更清楚地表明这些事情正在发生:

    f.foreach(g)
    f.flatMap(h)
    

    每当您看到foreach 时,它都会触发“一定会发生副作用”,这对于读者来说很重要。

    【讨论】:

      【解决方案2】:

      我对 Stew 的回答投了赞成票,但会补充说,如果您确实关心 g 是否失败,那么另一种写法是:

       f.flatMap{
         val ga = g(a)
         val ha = h(a)
      
         for{
           _ <- ga
           out <- ha
         } yield out
       }
      

      这将在不同线程中同时运行 hg 而不会跳过 h 但保留来自 g 的错误。

      【讨论】:

      • 在我的原始代码中,如果g(a) 抛出异常会怎样?
      • 除此之外,结果将是一个失败的未来
      • h(a) 还会运行吗?
      • 是的,这只是因为我没有将函数调用嵌套在 for-comp 中。
      • @fosskers 是的,完全正确。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-01
      • 2018-02-14
      • 2012-08-27
      • 2020-08-17
      • 1970-01-01
      • 2014-10-14
      • 1970-01-01
      相关资源
      最近更新 更多