22

if a scala function is

def A(): Either[Exception, ArrayBuffer[Int]] = {
...
}

what should be the right way to process the returned result? val a = A() and ?

theon
  • 14,170
  • 5
  • 51
  • 74
user398384
  • 1,124
  • 3
  • 14
  • 21
  • You can also use a Try[ArrayBuffer[Int]], this has the Exception part built in. In that case you have to pattern match: http://www.scala-lang.org/files/archive/nightly/docs/library/index.html#scala.util.Try – Jaap Nov 27 '13 at 18:15

3 Answers3

49

I generally prefer using fold. You can use it like map:

scala> def a: Either[Exception,String] = Right("On")

a.fold(l => Left(l), r => Right(r.length))
res0: Product with Either[Exception,Int] = Right(2)

Or you can use it like a pattern match:

scala> a.fold( l => {
     |   println("This was bad")
     | }, r => {
     |   println("Hurray! " + r)
     | })
Hurray! On

Or you can use it like getOrElse in Option:

scala> a.fold( l => "Default" , r => r )
res2: String = On
Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • 3
    I should mention that if you _only_ want to use it to map the right-hand side, `a.right.map(_.length)` is less typing and does what you want. Generally, the `.right` and `.left` methods make `Either` work a lot like option, except instead of preserving `None` as the other case like `Option` does, it preserves whatever the opposite side of the `Either` is. Likewise, `a.right.getOrElse` is simpler than `fold`. What I like about `fold` is that you can do all of these things at once and combine them. – Rex Kerr Aug 16 '10 at 20:59
  • The problem with using right.map is that you can't escape into left (e.g. make some Right values into a Left, e.g. if they're an error). – Andy Hayden Jan 25 '16 at 18:59
17

The easiest way is with pattern matching

val a = A()

a match{
    case Left(exception) => // do something with the exception
    case Right(arrayBuffer) => // do something with the arrayBuffer
}

Alternatively, there a variety of fairly straightforward methods on Either, which can be used for the job. Here's the scaladoc http://www.scala-lang.org/api/current/index.html#scala.Either

Rob
  • 415,655
  • 72
  • 787
  • 1,044
Dave Griffith
  • 20,435
  • 3
  • 55
  • 76
4

One way is

val a = A();
for (x <- a.left) {
  println("left: " + x)
}
for (x <- a.right) {
  println("right: " + x)
}

Only one of the bodies of the for expressions will actually be evaluated.

michid
  • 10,536
  • 3
  • 32
  • 59
  • Ok, this works, but in my opinion this is misusing `for` in an ugly way. If you see a `for`, you expect a loop, but here it's used as a kind of `if` statement. Pattern matching (see answer by Dave Griffith) is much cleaner and easier to understand. – Jesper Aug 17 '10 at 14:16
  • 3
    Well it depends. In Scala for expressions have broader semantics than looping. Basically everything which has map/flatmap can be used with for. This is convenient i.e. in the case of Option. – michid Aug 17 '10 at 16:16