/ / Комбиниране на Scala Фючърси и колекции в за разбиране - скала

Съчетаване на Scala фючърси и колекции в за разбиране - скала

Опитвам се да използвам for за изразяваневърху списък, след това направете трансформация на всеки елемент, използвайки помощна програма, която връща бъдеще. Накратко, той не се компилира и искам да разбера защо. Аз чета този въпрос, което е подобно и беше голяма помощ, но това, което се опитвам да направя, е дори по-просто, което е още по-объркващо, защо не работи. Опитвам се да направя нещо като:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

val numberList = List(1, 2, 3)
def squareInTheFuture(number: Int): Future[Int] = Future { number * number}
val allTheSquares = for {
number <- numberList
square <- squareInTheFuture(number)
} yield { square }

И това, което получавам, е:

грешка: несъответствие на типа; намерено: scala.concurrent.Future [Int] задължително: scala.collection.GenTraversableOnce [?] квадрат <- squareInTheFuture (номер) ^

Може ли някой да ми помогне да разбера защо това не работи и каква е най-добрата алтернатива?

Отговори:

7 за отговор № 1

flatMap изисква конструкторите на типа на numberList и squareInTheFuture(number) са едни и същи (по модул каквито и да е имплицитни преобразувания, които библиотеката за събиране прави). Това не е случаят тук. Вместо това, това е обиколка:

val allSquaresInTheFuture: Future[List[Int]] =
Future.traverse(numberList)(squareInTheFuture)

9 за отговор № 2

Най- Future придружаващ обект има traverse метод, който прави точно това, което искате:

val allTheSquares: Future[List[Int]] =
Future.traverse(numberList)(squareInTheFuture)

Това ще асинхронно започне всички изчисления и ще върне бъдеще, което ще бъде завършено, след като всички тези фючърси бъдат завършени.


2 за отговор № 3

@Lee е правилен. Като допълнение, ако се опитвате да направите паралелно изчисление:

  val numberList = List(1, 2, 3)
val allTheSquares = numberList.par.map(x => x * x)(breakOut)

Ако наистина искате Future:

val allTheSquares: Future[List[Int]] = Future.traverse(numberList)(squareInTheFuture)

2 за отговор № 4

Вашето за разбиране е същото като

val allTheSquares = numberList.flatMap(number => squareInTheFuture(number))

flatMap изисква функцията "аргумент" да се връща a GenTraversableOnce[Int]независимо от това, че вашият връща a Future[Int], оттук и несъответствието.