эквивалентно оператору JavaScript ||в скале - PullRequest
6 голосов
/ 04 января 2012

В javascript мы можем сделать что-то вроде:

value = f1() || f2() || f3();

, это вызовет f1 и присвоит ему значение, если результат не равен нулю.только если результат равен нулю, он вызывает f2 и присваивает ему значение, если оно не равно нулю....

Способ достижения этого в scala приведен здесь: Как сделать эту функцию с первым не нулевым результатом более элегантной / лаконичной? создать функцию getFirstNNWithOption, которая вызывает каждыйфункция, пока не нуль:

value = getFirstNNWithOption(List(f1 _, f2 _, f3 _))

Однако, это не так хорошо, как JavaScript ||оператор, который является более гибким.Например:

value = f1() || f2(3) || f3(44, 'ddd') || value4;

Есть ли способ достичь этого в Scala?

Ответы [ 5 ]

11 голосов
/ 04 января 2012

Поскольку вы используете функцию, возвращающую Option.

Лучшим решением было бы использовать опцию цепочки, как описано здесь Цепочка опций

Так чтоделать

f1().orElse(f2()).orElse(f3()).orElse(Some(4))
9 голосов
/ 04 января 2012

Я использую рекомендованный Option вместо null.
Например:

class OptionPimp[T](o: Option[T]) {
  def ||(opt: => Option[T]) = o orElse opt
  def ||(t: => T) = o getOrElse t
}
implicit def optionPimp[T](o: Option[T]) = new OptionPimp(o)

def f1(): Option[Int] = None
def f2(): Option[Int] = None
def f3(): Option[Int] = Some(3)

val value1 = f1() || f2() || f3() || 4 // yields 3
val value2 = f1() || f2()         || 4 // yields 4
5 голосов
/ 04 января 2012

Если вы используете это с функциями, которые могут возвращать нуль, вы также можете определить оператор слияния нуль:

class NullOption[A <: AnyRef](a: A) {
  def |?|[B >: A](b: => B) = if (a ne null) a else b
}
implicit def null_handling[A <: AnyRef](a: A) = new NullOption(a)

, который работает так же, как и Javascript.(Я использовал |?|, чтобы не принять его за логическое или логическое, но вы можете использовать ||, если хотите.) Это работает даже лучше - почти как Option - если вы добавляете условную карту (здесь с именем ? - выберите ваше любимое слово или символ):

class NullOption[A <: AnyRef](a: A) {
  def |?|[B >: A](b: => B) = if (a ne null) a else b
  def ?[C >: Null](f: A => C): C = if (a ne null) f(a) else null
}
implicit def null_handling[A <: AnyRef](a: A) = new NullOption(a)

Тогда вы можете

scala> val s: String = null
s: String = null

scala> val t: String = "foo"
t: String = foo

scala> s?(_.toUpperCase) |?| t |?| { println("I am not executed"); "bar" }
res4: java.lang.String = "foo"

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

4 голосов
/ 04 января 2012

Я в значительной степени придерживаюсь того же мнения, что и Энди , за исключением того, что я бы использовал обозначение оператора и использовал правильный метод по умолчанию:

value = f1 orElse f2(3) orElse f3(44, 'ddd') getOrElse value4
1 голос
/ 27 июня 2013

С новым scala 2.10 вы можете использовать неявные классы для обновления ответа @PeterSchmitz, поэтому вам не нужно определять функцию неявного преобразования.

implicit class OptionPimp[T](o: Option[T]) {
  def ||(opt: => Option[T]) = o orElse opt
  def ||(t: => T) = o getOrElse t
}

То же самое для ответа Рекс Керр:

implicit class NullOption[A <: AnyRef](a: A) {
  def |?|[B >: A](b: => B) = if (a ne null) a else b
  def ?[C >: Null](f: A => C): C = if (a ne null) f(a) else null
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...