Reputation: 12710
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
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
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
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
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
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