Equivalent to javascript operator || in scala

In javascript we can do something like:

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

this will call f1 and assign it a value if the result is not NULL. only if the result is zero, it will call f2 and assign it a value if it is not null. ...

The following is a way to achieve this goal in scala: How to make this function with a first-non-zero result more elegant / concise? create a getFirstNNWithOption function that calls each function to zero:

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

However, this is not as good as javascript || operator who is more flexible. eg:

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

is there any way to achieve this in scala?

+6
source share
5 answers

I use the recommended Option instead of null .
For instance:

 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 
+9
source

Since you are using a function that returns Option .

A better solution would be to use the Chaining Option, as described here.

So you would do

 f1().orElse(f2()).orElse(f3()).orElse(Some(4)) 
+11
source

If you use this with functions that can 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. (I used |?| Not to make a mistake in the logical boolean or, but you can use || if you want.) This works even better - almost like Option - if you add a conditional card (here called ? - select 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 will not help you remember that you need to handle no-data cases, but it can make handling with a null value a little more enjoyable (at least as long as there are no primitives; with primitives, returning zero -primitive, actually does not make sense).

+5
source

To a large extent, I am of the same opinion as Andy , except that I use operator notation and use the correct default method:

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

With the new scala 2.10, you can use implicit classes to update @PeterSchmitz's answer, so you don't 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 } 

The same goes for Rex Kerr's 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 } 
+1
source

Source: https://habr.com/ru/post/905079/


All Articles