Scala Either type: How to get the value out of an Either

Scala Either FAQ: How do I get the value out of a Scala Either?

Solution

In this recipe I show many different ways to get the value out of a Scala Either, while accounting for the fact that an Either value may be a success value (a Right) or a failure value (a Left).

First, we start with a little setup work:

import scala.util.control.Exception.*

def makeInt(s: String): Either[Throwable, Int] = 
    allCatch.either(s.toInt)

val eLeft  = makeInt("yo")    // Left
val eRight = makeInt("42")    // Right

As shown in those last comments, eLeft is a Left value because "yo" cannot be converted to an Int, and eRight is a Right value because "42" can be converted.

Now let’s look at how to work with these Either values.

Recommended approaches

These first solutions show the recommended way to work with Scala Either values. Because you don’t initially know if an Either is a Left or a Right, you have to assume that it can be either, so you work with it that way.

One solution is to use a match expression:

val b: Int | Throwable = a match
    case Right(value) => value
    case Left(error) => error

Another slightly less verbose solution is to use fold:

val b: Throwable | Int = eRight.fold(
    error => error,
    value => value
)

Depending on your situation, getOrElse can be another good solution:

val b = eLeft.getOrElse(0)    // 0
val b = eRight.getOrElse(0)   // 42

Note that a result like 0 isn’t always the “correct” solution, because the input value may be "yo" or it may be "0", and there’s no way for you to differentiate that.

Just use the Either

Also note that another usual approach is to just write your code like normal, only really worrying about the success case, and the failure case eventually takes care of itself. Somewhere in the history of Scala, someone referred to this as “Happy Path Programming,” because you just write your algorithm for the success case, and the failure case automatically takes care of itself.

So if you need to map a value, you do that:

val c = eLeft.map(_ * 10)   // Left(value = java.lang.NumberFormatException: For input string: "yo")
val c = eRight.map(_ * 10)  // Right(42)

As shown, the result of a map is another Either, so you don’t have to deal with the issue of whether it’s a Left or a Right right now. That can be handled with a match or fold expression later.

Similarly, this is what a for-expression looks like:

val rez = for
    a <- eLeft
    b = a * 10
yield
    b
// Left(NumberFormatException: For input string: "yo")

val rez = for
    a <- eRight
    b = a * 10
yield
    b
// rez: Right(420)

And notice how foreach works:

repl> val c = eRight.foreach(println)
42

repl> val c = eLeft.foreach(println)

In the case of eLeft, which is a Left value, there is no output. This can be a useful approach, when you need it.

Other Right and Left solutions

I’m running out of time for today, so for now I’ll just show some more examples, with their results shown after each comment. Notice the difference between the Left value:

eLeft.getOrElse(0)    // 0

eLeft.exists(_ > 0)   // false

eLeft.isLeft          // true
eLeft.isRight         // false

eLeft.toSeq           // List()
eLeft.toSeq(0)        // java.lang.IndexOutOfBoundsException: 0
eLeft.map(_ * 10)     // Either[Throwable, Int] = 
                      //     Left(value = java.lang.NumberFormatException: For input string: "yo")

eLeft.canEqual(0)     // false

and the Right value in these examples:

eRight.getOrElse(0)    // 42

eRight.exists(_ > 0)   // true

eRight.isLeft          // false
eRight.isRight         // true

eRight.toSeq           // List(42)
eRight.toSeq(0)        // 42
eRight.map(_ * 10)     // Right(420)

eRight.canEqual(0)     // false

Option has many more methods

Also note that the Option data type has many more functions than the Either data type, so some developers like to immediately convert an Either to an Option, and then work with the methods on the Option types.

Here are some success (Some) examples:

eRight.toOption.get            // 42
eRight.toOption.getOrElse(0)   // 42
eRight.toOption.head           // 42
eRight.toOption.headOption     // Some(42)
eRight.toOption.isDefined      // true
eRight.toOption.isEmpty        // false
eRight.toOption.size           // 1
eRight.toOption.tail           // List()

eRight.toOption.take(0)        // List()
eRight.toOption.toList         // List(42)

And here are the failure (None) examples:

eLeft.toOption.get            // java.util.NoSuchElementException: None.get
eLeft.toOption.getOrElse(0)   // 0
eLeft.toOption.head           // java.util.NoSuchElementException: head of empty list
eLeft.toOption.headOption     // None
eLeft.toOption.isDefined      // false
eLeft.toOption.isEmpty        // true
eLeft.toOption.size           // 0
eLeft.toOption.tail           // java.lang.UnsupportedOperationException: tail of empty list

eLeft.toOption.take(0)        // List()
eLeft.toOption.toList         // List()

One key here is to note all those exceptions that can be thrown when you end up with a None. Some people try to access the value directly with get, but if that doesn’t work, you’ll get an exception.

Summary

In summary, if you want to get the value out of a Scala Either, I hope these examples are helpful. Also, I’ll try to update the examples at the end of this article when I have more time.