Как я могу элегантно вернуть карту во время работы - PullRequest
0 голосов
/ 13 марта 2019

Я новичок в Scala, перешел с Java, и у меня возникли проблемы с элегантным возвратом Map из этой функции.Какой элегантный способ переписать эту функцию, чтобы она не имела такого ужасного повторения?

    val data = getData
    if (someTest(data)) {
        val D = doSomething(data)
        val E = doWork(D)
        if (someTest2(E)) {
             val a = A()
             val b = B()
             Map(a -> b)
        } else {
           Map.empty
        }
    } else {
        Map.empty
    }

Ответы [ 3 ]

2 голосов
/ 13 марта 2019

Если у вас есть проблема с подключением слишком большого числа условий с помощью &&, вы можете поместить все в естественную монаду с коротким замыканием (а именно Option), выполнить несколько шагов filter и map замените результат на Map(A() -> B()), если все тесты пройдены успешно, а затем разверните Option с getOrElse в конце:

Option(getData)
  .filter(someTest)
  .map(doSomething andThen doWork)
  .filter(someTest2)
  .map(_ => Map(A() -> B()))
  .getOrElse(Map.empty)

Таким образом, вы можете организовать свой код "более вертикально".

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

Андрей отвечает правильно, но логику также можно записать с помощью оператора for:

(for {
  data <- Option(getData) if someTest(data)
  d = doSomething(data)
  e = doWork(d) if someTest2(e)
} yield {
  Map(A() -> B())
}).getOrElse(Map.empty)

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

Обратите внимание, что я сохранил значения d и e в предположении, что они действительно значимы в реальном коде. Если нет, то может быть одно if выражение, которое выполняет все тесты, как отмечено в других ответах:

(for {
  data <- Option(getData)
  if someTest(data) && someTest2(doWork(doSomething(data)))
} yield {
  Map(A() -> B())
}).getOrElse(Map.empty)
0 голосов
/ 13 марта 2019

Вы можете переписать, чтобы воспользоваться преимуществами короткого замыкания, если вы упоминаете блоки else с Map.empty в качестве повторения.

val data = getData
if (someTest(data) && someTest2(doWork(doSomething(data)))) {
  val a = A()
  val b = B()
  Map(a -> b)
} else {
    Map.empty
}

Второе решение с использованием отложенной оценки:

val data = getData
lazy val D = doSomething(data)
lazy val E = doWork(D)

if (someTest(data) && someTest2(E)) {
  val a = A()
  val b = B()
  Map(a -> b)
} else {
  Map.empty
}

D, E и someTest2 (E) не будут оцениваться, если someTest (data) имеет значение false.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...