Kevin Meredith
Kevin Meredith

Reputation: 41909

Getting Value of Either

Besides using match, is there an Option-like way to getOrElse the actual content of the Right or Left value?

scala> val x: Either[String,Int] = Right(5)
scala> val a: String = x match { 
                                case Right(x) => x.toString
                                case Left(x) => "left" 
                       }
a: String = 5

Upvotes: 34

Views: 43164

Answers (5)

vasigorc
vasigorc

Reputation: 962

If for some case you cannot use cats.Validated then for cases when you have a collection (e.g. a List[_]) of Either[L, R] you could do this:

val list: List[Either[Throwable, String]] = ...
val throwablesList = list.collect { Left(ex) => ex }

Upvotes: 0

Mario Galic
Mario Galic

Reputation: 48410

Given type A on both sides, that is, Either[A, A], we can use Either.merge

...to extract values from Either instances regardless of whether they are Left or Right.

Note if left and right types differ then result is least upper bound of the two types which may become in worst case Any:

val e: Either[Int, String] = Right("hello")
e.merge // hello: Any

Upvotes: 3

lex82
lex82

Reputation: 11297

In Scala 2.12 there is a getOrElse method for getting the "right" value but you cannot use it for the "left" value directly. However, you can do it like this: e.swap.getOrElse(42).

Upvotes: 2

Kristian Domagala
Kristian Domagala

Reputation: 3696

Nicolas Rinaudo's answer regarding calling getOrElse on either the left or right projection is probably the closest to Option.getOrElse.

Alternatively, you can fold the either:

scala> val x: Either[String,Int] = Right(5)
x: Either[String,Int] = Right(5)

scala> val a: String = x.fold(l => "left", r => r.toString)
a: String = 5

As l is not used in the above fold, you could also write x.fold(_ => "left", r => r.toString)

Edit: Actually, you can literally have Option.getOrElse by calling toOption on the left or right projection of the either, eg,

scala> val o: Option[Int] = x.right.toOption
o: Option[Int] = Some(5)

scala> val a: String = o.map(_.toString).getOrElse("left")
a: String = 5

Upvotes: 23

Nicolas Rinaudo
Nicolas Rinaudo

Reputation: 6168

I don't particularly like Either and as a result I'm not terribly familiar with it, but I believe you're looking for projections: either.left.getOrElse or either.right.getOrElse.

Note that projections can be used in for-comprehensions as well. This is an example straight from the documentation:

def interactWithDB(x: Query): Either[Exception, Result] =
  try {
    Right(getResultFromDatabase(x))
  } catch {
    case ex => Left(ex)
  }

// this will only be executed if interactWithDB returns a Right
val report =
  for (r <- interactWithDB(someQuery).right) yield generateReport(r)
if (report.isRight)
  send(report)
else
  log("report not generated, reason was " + report.left.get)

Upvotes: 20

Related Questions