David Portabella
David Portabella

Reputation: 12710

equivalent to the javascript operator || in scala

In javascript, we can do something like:

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

this will call f1, and assign it to value if the result is not null. only if the result is null, it will call f2, and assign it to value if that is not null. ...

A way to achieve this in scala is given here: How to make this first-not-null-result function more elegant/concise? create a getFirstNNWithOption function that calls each function until not null:

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

However, this is not as nice as the javascript || operator, which is more flexible. eg:

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

is there a way to achieve this in scala?

Upvotes: 6

Views: 417

Answers (5)

Mikaël Mayer
Mikaël Mayer

Reputation: 10681

With the new scala 2.10, you can use implicit classes to update @PeterSchmitz answer, so you do not need to define an implicit conversion function.

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

Same for Rex Kerr answer:

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
}

Upvotes: 1

Peter Schmitz
Peter Schmitz

Reputation: 5844

I am using the recommended Option instead of null.
For example:

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

Upvotes: 9

Rex Kerr
Rex Kerr

Reputation: 167871

If you are using this with functions that may return null, you can also define a null-coalescing operator:

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)

which works just like Javascript's. (I have used |?| in order to avoid mistaking it for boolean logical or, but you can use || if you prefer.) This works even better--almost like Option--if you add a conditional map (here named ?--pick your favorite word or symbol):

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)

Then you can

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"

Of course, your type system won't help you remember that you need to handle there-is-no-data cases, but it can make null-handling slightly more pleasant (at least as long as there are no primitives; with primitives, returning null-or-primitive doesn't really make sense).

Upvotes: 5

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297155

I'm pretty much of the same opinion as Andy, except I'd use operator notation, and use the proper method for default:

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

Upvotes: 4

Andy Petrella
Andy Petrella

Reputation: 4345

Since your are using function returning Option.

The best solution would be to use Chaining Option like it is explained here Option's chaining

So you would do

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

Upvotes: 11

Related Questions