Trying to understand why the following expression yields Future[Nothing] and not 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
of course, this is simplified example, and I can return the fooList directly. But I am trying to understand the reason of getting Future[Nothing]
and not Future[List[Int]]
I get a compiler error for your code, which is expected since fooList.distinct
should have been a Future
for the extractor <-
to work on it.
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
^
This code compiles:
scala> for(fooList <- foo(); f = fooList.distinct) yield f
res4: scala.concurrent.Future[List[Int]] = scala.concurrent.impl.Promise$DefaultPromise@1e387e13
And this code also (wrapping the call to distinct
into a 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
Scala's for-comprehension are just syntactic sugar for methods flatMap
, map
and filter
. A code
for {
x1 <- e1
x2 = e2
x3 <- e3 if e4
x4 <- e5
} yield e6
translates into (or something equivalent to)
e1.flatMap(x1 =>
e2.map(x2 =>
e3.filter(x3 => e4).flatMap(x3 =>
e5.map(x4 => e6)
The for-comprehension in your example becomes
foo().flatMap(fooList => fooList.distinct.map(f => f))
which is equivalent to
foo().flatMap(fooList => fooList.distinct)
because map(id) = id
by definition of what a Functor is. The method foo().flatMap
takes an argument of type List[Int] ⇒ Future[S]
. But the function fooList => fooList.distinct
is of type List[Int] => List[Int]
. The compiler checks if the provided type is a subtype of the expected one. In your case the check falls to: is List[Int]
a subtype of Future[S]
for some type S
. I'm not sure why the exepected type S
is Nothing
but it may be related to Future
being covariant (as any Functor
should).
Given a future of type Future[T]
, map
and flatMap
both produce a Future[S]
but the difference is:
map
takes arguments of type T => S
. Syntax x = ...
. flatMap
takes arguments of type T => Future[S]
. Syntax x <- ...
. The method you want is then map
which gives
for (fooList <- foo())
yield fooList.distinct
or
foo().map(fooList => fooList.distinct)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.