Type Inconsistency in Scala For understanding: scala.concurrent.Future

I'm new to Scala, please bear with me. I have a bunch of futures wrapped in a large array. Futures did the hard work looking at several TB of data and at the end of my application I want to wrap up all the results of the specified futures so I can represent them nicely.

The collection of futures I have is of the following type:

Array[Future[List(String, String, String)]]

      

Everything I've read so far about understanding shows that

val test: Seq[Seq[List[String]]] = Seq(Seq(List("Hello", "World"), List("What's", "Up")))

val results = for {
  test1 <- test
  test2 <- test1
  test3 <- test2
} yield test3

      

Results in

results: Seq[String] = List(Hello, World, What's, Up)

      

Following the same logic, I decided to do it this way, since I recently discovered that Option, Try, Failure and Success can be thought of as collections:

val futures = { ... } // Logic that collects my Futures

// futures is now Array[Future[List(String, String, String)]]

val results = for {
  // futureSeq as Seq[List(String, String, String]
  futureSeq <- Future.sequence(futures.toSeq)
  // resultSet as List(String, String, String)
  resultSet <- futureSeq
} yield resultset

      

But that won't work. I seem to be getting the following compilation errors:

Error: (78, 15) type mismatch,
found: Seq [List (String, String, String)]
required: scala.concurrent.Future [?]

resultSet <- futureSeq ^

The part with the required: scala.concurrent.Future [?] Throws me away completely. I don't understand why the future is needed here.

I have checked the types of all my objects through the REPL by debugging and using IntelliJ type checking. They seem to confirm that I'm not just confused about my types.

And before anyone notices, yes, I know the syntactic sugar for the group of maps, flatMaps and withFilters is understood to understand.

+3


source to share


1 answer


Details on how for

-comprehension handles are for calls flatMap

and map

are important here. This code:

for {
  futureSeq <- Future.sequence(futures.toSeq)
  resultSet <- futureSeq
} yield resultset

      

Becomes something more or less like this:

Future.sequence(futures.toSeq).flatMap(futureSeq => futureSeq)

      

flatMap

on Future

expects a function that returns Future

, but you specified one that returns Seq[List[(String, String, String)]]

.

In general, you cannot mix types in for

-comprehensions ( Option

in the sense of sequence, this is a kind of exception supported by implicit conversion). If you have an arrow <-

going out of the future, all of your other arrows <-

should come out of futures.



You probably want something like this:

val results: Future[Seq[(String, String, String)]] =
  Future.sequence(futures.toSeq).map(_.flatten)

      

Then you can use something like this:

import scala.concurrent.Await
import scala.concurrent.duration._

Await.result(results.map(_.map(doSomethingWithResult)), 2.seconds)

      

Submit results synchronously (block until they complete).

+2


source







All Articles