理解为什么未来的理解结果会产生未来[没什么]

时间:2016-03-08 08:06:08

标签: scala

试图理解为什么以下表达式产生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]]

的原因

2 个答案:

答案 0 :(得分:7)

我的代码出现了编译器错误,这是预期的,因为fooList.distinct应该是Future,因为提取器<-可以使用它。

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

答案 1 :(得分:3)

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 => fooList.distinct的类型为List[Int] => List[Int]。编译器检查提供的类型是否是预期类型的​​子类型。在您的情况下,检查属于: List[Int] 某种类型的 Future[S] 的子类型 {{1} }。我不确定为什么被请求的类型SS,但它可能与Nothing是协变的(因为任何Future都应该)。

鉴于类型为Functor的未来,Future[T]map都会生成flatMap,但区别在于:

  • Future[S]接受map类型的参数。 语法 T => S
  • x = ...接受flatMap类型的参数。 语法 T => Future[S]

您想要的方法是x <- ...,它提供

map

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