Scala. GetOrElse method

Why, when I print, everything works fine?

Right(2).left getOrElse Right(4).left getOrElse Left("Error") 

but when i print this compilation fails?

 Right[String, Int](2).left getOrElse Right[String, Int](4).left getOrElse Left[String, Int]("Error") 

Compilation Error:

GetOrElse is not a member of java.io.Serializable
println (RightString, Int.left getOrElse RightString, Int.left getOrElse LeftString, Int)

Therefore, I cannot call the getOrElse method getOrElse

+7
scala either
source share
1 answer

getOrElse Signatures for a LeftProjection[A, B] :

 def getOrElse[AA >: A](or: ⇒ AA): AA 

i.e. he expects the argument to have some type AA , which is a supertype of A

In the first example, you left type annotations, allowing the compiler to output Nothing for A Then you provided an argument of type LeftProjection[Nothing, Int] .

Since Nothing is a subtype of all types, LeftProjection[Nothing, Int] trivially a supertype! This special case in the type system means that he checked the type almost by accident.

However, the most specific common supertype of String and LeftProjection[String, Int] is Serializable .


So, if you want to bind Either s, you need a method that can take another Either[A, B] , not just A or B

The method you seem to want would look like this:

 def leftOrElse[A, B](e1: Either[A, B], e2: => Either[A, B]): Either[A,B] = e1 match { case Left(a) => Left(a) case Right(b) => e2 } 

(Similarly, you can write rightOrElse , which is a more common use case.)

This becomes syntactically more convenient if you make it an extension method using implicits.

 implicit class EitherOps[A, B](e1: Either[A, B]) { def leftOrElse(e2: => Either[A, B]): Either[A,B] = // as above } 

Since this expects Either[A, B] for both operands instead of A or B (or some supertype), you can link your Either s.

 scala> Right[String, Int](2) leftOrElse Right[String, Int](4) leftOrElse Left[String, Int]("Error") res1: Either[String,Int] = Left(Error) 
+8
source share

All Articles