Как сопоставить два «будущих» результата в Scala/ReactiveMongo?

У меня есть приложение, написанное с помощью Play и ReactiveMongo, где я хочу:

  • Создайте действие, которое вставляет landingPage документ в MongoDB.
  • Вставьте новую целевую страницу и дождитесь ее вставки.
  • Подсчитайте новое общее количество документов LandingPage и верните его пользователю.

У меня есть этот рабочий код:

// Insert the landing page and wait for it to be inserted, so we can then get the new count of landing pages.
val futures = for {
  wr <- landingPagesCollection.insert(landingPage)
  count <- landingPagesCollection.count()
} yield count

futures.map { (count: Int) =>
  Created(Json.obj(
    "created" -> true,
    "landingPage" -> landingPage.toJson,
    "count" -> count
  ))
}

Этот код работает нормально. Однако из любопытства я хочу знать, как получить доступ к значению wr (WriteResult). Когда я изменил код на:

val futures = for {
  wr <- landingPagesCollection.insert(landingPage)
  count <- landingPagesCollection.count()
} yield (wr, count)

futures.map { (wr: WriteResult, count: Int) =>
  Created(Json.obj(
    "created" -> true,
    "message" -> s"You created landing page ${landingPage.name} (${landingPage.jobNumber}). The Git URI is '${landingPage.gitUri}'.",
    "landingPage" -> landingPage.toJson,
    "count" -> count,
    "writeResult" -> wr
  ))
}

Я получаю следующие сообщения об ошибках:

Сообщение об ошибке

Кто-нибудь может объяснить, как получить доступ к wr в функции карты?


person Amy B    schedule 22.11.2015    source источник


Ответы (2)


Попробуйте изменить

futures.map { (wr: WriteResult, count: Int) =>

to:

futures.map { case (wr: WriteResult, count: Int) =>

или просто:

futures.map { case (wr, count) =>

Надеюсь это поможет

person Nyavro    schedule 22.11.2015
comment
Добавление case помогло! Спасибо! Можете ли вы объяснить, почему этот случай заставляет его работать? Я думал, что случай был для использования в блоках match. - person Amy B; 22.11.2015
comment
@AmyB Анонимная функция может быть определена последовательностью случаев §8.5 scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html - person sumnulu; 23.11.2015

Синтаксис, который вы использовали, работает, если функция принимает 2 аргумента, а не кортеж.

list.map((a: Int, b: String) => ...)

если вам нужен кортеж, вы можете сделать это:

list.map(tuple: (Int, String) => {
   val (num, str) = tuple
   ...
})

или передать частичную функцию, как предложено в принятом ответе. Он будет соответствовать аргументу (соответствует кортежу) и позволит вам использовать извлеченные значения позже.

list.map { case (a: Int, b: String) => ... }

обратите внимание, что в этом случае требуются фигурные скобки.

Аннотации типов можно отбросить, поскольку они могут быть определены компилятором.

person Łukasz    schedule 22.11.2015