Как я могу сделать сопоставление с образцом на кортеже с ленивой инициализацией? - PullRequest
0 голосов
/ 05 сентября 2018

У меня есть сценарий, когда мне нужно вызвать до трех служб, чтобы что-то сделать. Каждый сервис имеет некоторый приоритет, и мой алгоритм зависит от комбинации результата каждого сервиса (все они, два или даже один). Чтобы справиться с этой ситуацией, я хочу использовать сопоставление с образцом (потому что совпадения и извлечение переменной)

Вот вам упрощенный пример.

case class Foo(bar: String, baz: Option[String])

def expensiveOperation1(): String = ???
def expensiveOperation2(): List[Int] = ???
def expensiveOperation3(): Foo = ???

lazy val r1 = expensiveOperation1()
lazy val r2 = expensiveOperation2()
lazy val r3 = expensiveOperation3()

(r1, r2, r3) match {
  case ("Value1", _, _)          => "1"
  case ("Value2", _, _)          => "2"
  case (_, List(1), _)           => "3"
  case (_, Nil, _)               => "4"
  case ("Value3", 1 :: tail, _)  => "5" + tail
  case (_, _, Foo("x", Some(x))) => x
  case (_, _, _)                 => "7"
}

Как вы можете видеть, нет необходимости постоянно вызывать дорогиеOperation2 и дорогойOperation3, но, хотя я сохраняю каждый результат в отложенных значениях, в момент, когда я создаю Tuple3, вызывается каждый метод.

Я мог бы создать контейнер LazyTuple3 с вызовом из трех параметров по имени, чтобы решить эту проблему, но я получу новую проблему, метод unapply (LazyTuple3.unapply) возвращает Option, поэтому после первого «case» каждый метод будет вызван.

Я мог бы решить это с помощью вложенного «если» или «совпадения», но я хочу дать шанс с одним «совпадением», я нахожу это более ясным.

Есть идеи?

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

1 Ответ

0 голосов
/ 05 сентября 2018

Попробуйте использовать scalaz.Need. https://static.javadoc.io/org.scalaz/scalaz_2.12/7.2.26/scalaz/Need.html

case class Foo(bar: String, baz: Option[String])

def expensiveOperation1(): String = {
    println("operation1")
    "Value3"
}
def expensiveOperation2(): List[Int] = {
    println("operation2")
    List(1, 2, 3)
}
def expensiveOperation3(): Foo = {
    println("operation3")
    Foo("x", Some("x"))
}

lazy val r1 = Need(expensiveOperation1())
lazy val r2 = Need(expensiveOperation2())
lazy val r3 = Need(expensiveOperation3())

(r1, r2, r3) match {
    case (Need("Value1"), _, _)                => "1"
    case (Need("Value2"), _, _)                => "2"
    case (_, Need(List(1)), _)                 => "3"
    case (_, Need(Nil), _)                     => "4"
    case (Need("Value3"), Need(1 :: tail), _)  => "5" + tail
    case (_, _, Need(Foo("x", Some(x))))       => x
    case (_, _, _)                             => "7"
}

Это напечатает:

    operation1
    operation2
...