Каков наилучший способ объединить два будущих[Карта[T1, T2]] в Scala

#scala

Вопрос:

У меня есть список имен файлов, и я хочу загружать соответствующие страницы пакетами (а не все сразу). Для этого я использую FoldLeft и пишу агрегатную функцию, которая агрегирует будущую[Карту[T1,T2]].

 def loadPagesInBatches[T1, T2](fileNames: Set[FileName]): Future[Map[T1, T2]] = {
   val fileNameToPageId: Map[FileName, PageId] = ... //invokes a function that returns the pageId correlated to the fileName.
   val batches: Iterator[Set[FileName]] = fileNames.grouped(10) //batches of 10;
   batches.foldLeft(Future(Map.empty[T1, T2]))(aggregate(fileNameToPageId))
}
 

И подпись aggregate выглядит следующим образом:

 def aggregate(fileNameToPageId: Map[FileName, PageId]): (Future[Map[T1, T2]], Set[FileName]) => Future[Map[T1, T2]] = {..}
 

Я пытаюсь убедиться, что это лучший способ объединить эти будущие[Карты].

Заранее спасибо!

P. S: FileName и PageId это просто типы строк.

Ответ №1:

В случае, если у вас есть ровно 2 варианта будущего, это, zipWith вероятно, будет наиболее идиоматичным.

 val future1 = ???
val future2 = ???

future1.zipWith(future2)(_    _)
 

Что является более коротким способом написания а для понимания:

 for {
  map1 <- future1
  map2 <- future2
} yield map1    map2
 

Хотя zipWith потенциально может быть реализована какая-то оптимизация.

Комментарии:

1. Но у меня есть более 2 карт. Допустим, у меня есть 100 файлов, и я беру пакеты по 10. Это будет означать, что у меня есть 10 карт из этих пакетов и 1 пустая карта, с которой я начинаю в reduceLeft функции.

2. У меня есть только две карты в моей подфункции, если вы это имели в виду.

3. Да, я имею в виду, если у вас есть 2 Future[Map[A,B]] локально в вашей функции.

4. Спасибо. Первый вариант действительно работает (второй-нет; вероятно, потому, что map2 не в моем понимании, как вы можете видеть в моем решении).

Ответ №2:

Мое решение состояло в том, чтобы поместить две карты в список и использовать Future.reduceLeft .

 def aggregate(fileNameToPageId: Map[FileName, PageId]): (Future[Map[T1, T2]], Set[FileName]) => Future[Map[T1, T2]] = {
   case (all, filesBatch) => 
      val mapOfPages: Future[Map[NodeId, T]] = for {
         ... //Some logic
      } yield "TheBatchMap"
      Future.reduceLeft(List(all, mapOfPages))(_    _)
}