Как сопоставить образец по нескольким вещам для понимания - PullRequest
3 голосов
/ 14 марта 2019

У меня есть для понимания, в котором есть 7 вещи.Вещи 7 выполняют запросы к БД в Slick и могут не возвращать никаких данных.Когда они не возвращают никаких данных, я хочу, чтобы значения по умолчанию помещали это.Я могу сделать следующее, если была только 1 вещь, но как мне сделать это, когда у меня есть 7?

case class MyType(one: String, two: Int, three: Int)

//What I could do for 1 thing
for {
  thing1: Option[MyType] <- repo.queryForThing1()
}
yield {
  thing1 match {
   case Some(t) => MyOtherType(Seq(t))
   case None => MyOtherType(Seq(MyType("thing1", 0, 0)))
  }
}

//What do I do for when I have 7 things??
for {
  thing1: Option[MyType] <- repo.queryForThing1()
  thing2: Option[MyType] <- repo.queryForThing2()
  thing3: Option[MyType] <- repo.queryForThing3()
  thing4: Option[MyType] <- repo.queryForThing4()
  thing5: Option[MyType] <- repo.queryForThing5()
  thing6: Option[MyType] <- repo.queryForThing6()
  thing7: Option[MyType] <- repo.queryForThing7()
}
yield {
  thing1 match {
   case Some(t) => MyOtherType(Seq(t))
   case None => MyOtherType(Seq(MyType("thing1", 0, 0)))
  }
}

Вопрос

Как можноЯ образец совпадения для 7 вещей?Каждый из них будет иметь значение по умолчанию thing<number>, когда оно None

Ответы [ 2 ]

1 голос
/ 14 марта 2019

Попробуй это! но это не сексуальный код: D

for {
  thing1: Option[String] <- repo.queryForThing1()
  thing2: Option[String] <- repo.queryForThing2()
  thing3: Option[String] <- repo.queryForThing3()
  thing4: Option[String] <- repo.queryForThing4()
  thing5: Option[String] <- repo.queryForThing5()
  thing6: Option[String] <- repo.queryForThing6()
  thing7: Option[String] <- repo.queryForThing7()
} yield (thing1, thing2, thing3, thing4, thing5, thing6, thing7) match {
  case (a, b, c, c, d, e, f) => ( 
    a.getOrElse("default"),
    b.getOrElse("default"),
    c.getOrElse("default"),
    c.getOrElse("default"),
    d.getOrElse("default"),
    e.getOrElse("default"),
    f.getOrElse("default")
  )
}

0 голосов
/ 15 марта 2019

Поскольку MyOtherType принимает последовательность, вы можете создать последовательность запросов и сопоставить ее с результатом:

Future.sequence(List(
  repo.queryForThing1().map(_.getOrElse(MyType("1", 1, 7))),
  repo.queryForThing2().map(_.getOrElse(MyType("2", 2, 6))),
  repo.queryForThing3().map(_.getOrElse(MyType("3", 3, 5))),
  repo.queryForThing4().map(_.getOrElse(MyType("4", 4, 4))),
  repo.queryForThing5().map(_.getOrElse(MyType("5", 5, 3))),
  repo.queryForThing6().map(_.getOrElse(MyType("6", 6, 2))),
  repo.queryForThing7().map(_.getOrElse(MyType("7", 7, 1)))
)).map(MyOtherType)

Однако это отличается от исходного кода тем, что он выполняет все запросы нав то же время, а не последовательно, и не остановится рано, если один из запросов завершится неудачей.

Тот факт, что у вас есть семь разных запросов и семь разных значений по умолчанию, означает, что вам придется записывать их по отдельности, так чтоэто всегда будет выглядеть немного грязно.


Для справки, вот версия, которая выполняет запросы последовательно, а не параллельно, но это не красиво!

val queries =
  List(
    repo.queryForThing1 _ -> MyType("1", 1, 7),
    repo.queryForThing2 _ -> MyType("2", 2, 6),
    repo.queryForThing3 _ -> MyType("3", 3, 5),
    repo.queryForThing4 _ -> MyType("4", 4, 4),
    repo.queryForThing5 _ -> MyType("5", 5, 3),
    repo.queryForThing6 _ -> MyType("6", 6, 2),
    repo.queryForThing7 _ -> MyType("7", 7, 1)
  )

queries.foldLeft(Future.successful(Vector.empty[MyType])) {
  case (prev, (query, default)) =>
    prev.flatMap(p => query().map(q => p :+ q.getOrElse(default)))
}.map(MyOtherType)
...