【问题标题】:understanding why future result with for comprehension yields Future[Nothing]理解为什么未来的结果与理解会产生未来[无]
【发布时间】:2016-03-09 16:29:53
【问题描述】:

试图理解为什么下面的表达式会产生 Future[Nothing] 而不是 Future[List[Int]]

def foo(): Future[List[Int]] = Future(List(1,2,3,3,3,4,4,4))
def bar(): Future[Nothing] =for {
    fooList <- foo()
    f <- fooList.distinct
} yield f

当然,这是简化的例子,我可以直接返回 fooList。但我试图了解获得Future[Nothing] 而不是Future[List[Int]] 的原因

【问题讨论】:

  • 我在控制台上得到一个类型不匹配,这正是我所期望的。

标签: scala


【解决方案1】:

您的代码出现编译器错误,这是预料之中的,因为 fooList.distinct 应该是 Future 以供提取器 &lt;- 处理。

scala> def foo() = Future(List(1,2,2,3))
foo: ()scala.concurrent.Future[List[Int]]


scala> for(fooList <- foo(); f <- fooList.distinct) yield f
<console>:17: error: type mismatch;
 found   : List[Int]
 required: scala.concurrent.Future[?]
              for(fooList <- foo(); f <- fooList.distinct) yield f
                                      ^

这段代码编译:

scala> for(fooList <- foo(); f = fooList.distinct) yield f
res4: scala.concurrent.Future[List[Int]] = scala.concurrent.impl.Promise$DefaultPromise@1e387e13

还有这段代码(将对distinct 的调用封装到Future 中):

scala> for(fooList <- foo(); f <- Future(fooList.distinct)) yield f
res5: scala.concurrent.Future[List[Int]] = scala.concurrent.impl.Promise$DefaultPromise@623d211
res4: scala.concurrent.Future[List[Int]] = scala.concurrent.impl.Promise$DefaultPromise@1e387e13

【讨论】:

  • 谢谢。 (它是在IDE上编译的,应该尝试过repl)
  • 这个答案没有解释为什么OP的方法无效。
  • @Haspemulator 第一句话呢?我可以更深入地解释它。但也许这并不总是有帮助。
【解决方案2】:

Scala 的 for-comprehension 只是方法 flatMapmapfilter 的语法糖。一个代码

for {
  x1 <- e1
  x2 =  e2
  x3 <- e3 if e4
  x4 <- e5
} yield e6

翻译成(或等价于)

e1.flatMap(x1 =>
e2.map(x2 =>
e3.filter(x3 => e4).flatMap(x3 =>
e5.map(x4 => e6)

你的例子中的 for-comprehension 变成了

foo().flatMap(fooList => fooList.distinct.map(f => f))

相当于

foo().flatMap(fooList => fooList.distinct)

因为map(id) = id 定义为Functor。方法foo().flatMap 采用List[Int] ⇒ Future[S] 类型的参数。但是函数fooList =&gt; fooList.distinct 的类型是List[Int] =&gt; List[Int]。编译器检查提供的类型是否是预期类型的​​子类型。在您的情况下,检查属于: List[Int] 一个子类型 Future[S] 对于某些类型 S。我不确定为什么预期的类型 SNothing 但它可能与 Future 是协变的(就像任何 Functor 应该的那样)。

鉴于Future[T] 类型的future,mapflatMap 都产生Future[S],但区别在于:

  • map 接受 T =&gt; S 类型的参数。 语法 x = ... .
  • flatMap 接受 T =&gt; Future[S] 类型的参数。 语法 x &lt;- ... .

然后你想要的方法是map,它给出了

for (fooList <- foo())
yield fooList.distinct

foo().map(fooList => fooList.distinct)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多