相当于javascript运算符||在斯卡拉

时间:2012-01-04 10:42:50

标签: scala

在javascript中,我们可以执行以下操作:

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

这将调用f1,如果结果不为null,则将其赋值给value。 只有当结果为null时,它才会调用f2,并且如果它不为null,则将其赋值给value。 ...

这里给出了一种在scala中实现此目的的方法:How to make this first-not-null-result function more elegant/concise? 创建一个getFirstNNWithOption函数,调用每个函数直到不为null:

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

然而,这不如javascript ||那么好运营商,更灵活。例如:

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

有没有办法在scala中实现这个目标?

5 个答案:

答案 0 :(得分:11)

由于您正在使用返回Option的函数。

最好的解决方案是使用链接选项,就像这里解释Option's chaining

一样

所以你会这样做

f1().orElse(f2()).orElse(f3()).orElse(Some(4))

答案 1 :(得分:9)

我使用推荐的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

答案 2 :(得分:5)

如果您对可能返回null的函数使用它,您还可以定义一个空合并运算符:

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"

当然,你的类型系统不会帮助你记住你需要处理那些没有数据的情况,但它可以使空处理稍微更愉快(至少只要没有原语;使用原语,返回null-or-primitive实际上没有意义。)

答案 3 :(得分:4)

我与Andy几乎一样,除了我使用运算符表示法,并使用正确的默认方法:

value = f1 orElse f2(3) orElse f3(44, 'ddd') getOrElse value4

答案 4 :(得分:1)

使用新的scala 2.10,您可以使用隐式类来更新@PeterSchmitz答案,因此您无需定义隐式转换函数。

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

Rex Kerr回答:

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
}