DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Modernizing Apache Spark Applications With GenAI: Migrating From Java to Scala
  • Mastering Advanced Aggregations in Spark SQL
  • Thermometer Continuation in Scala
  • Deploying a Scala Play Application to Heroku: A Step-by-Step Guide

Trending

  • How to Interpret the Number of Spring ApplicationContexts in Integration Tests
  • The AI Autonomy Spectrum: 7 Architecture Patterns for Intelligent Applications
  • The Documentation Crisis Nobody Sees: Why AI Agents Are Breaking Faster Than Humans Can Document Them
  • Native SQL in Java Without JDBC Boilerplate — Meet Ujorm3
  1. DZone
  2. Coding
  3. Languages
  4. Use of Either in Scala

Use of Either in Scala

In this article, we are going to see the use of Either in Scala. We use options in Scala but why do we want to go for Either? Either is a better approach.

By 
Jyoti Sachdeva user avatar
Jyoti Sachdeva
·
Jul. 06, 20 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
5.4K Views

Join the DZone community and get the full member experience.

Join For Free

In this article, we are going to see the use of Either in scala. We use Options in scala but why do we want to go for Either?

Either is a better approach in the respect that if something fails we can track down the reason, which in Option None case is not possible.

We simply pass None but what is the reason we got None instead of Some. We will see how to tackle this scenario using Either.

Scala
 




xxxxxxxxxx
1


 
1
Either[Left, Right]


None is similar to Left which signifies Failure and Some is similar to Right which signifies Success.

Let's see with help of an example:

Scala
 




x


 
1
 def returnEither(value: String): Either[NumberFormatException, Int] =
2
  {
3
    try {
4
      Right(value.toInt)
5
    } catch {
6
      case ex: NumberFormatException => Left(ex)
7
    }
8
  }
9
returnEither("abc").map(x => println(x))


It will not print anything, Either is right biased and returnEither("abc") gives Left(java.lang.NumberFormatException: For input string: "abc")

Now let's call it on Right value.

Scala
 




xxxxxxxxxx
1


 
1
returnEither("1").map(x => println(x))


It will print 1. Yes, it is right biased as the map works on Either.right. What if i want to call map on left?

Scala
 




xxxxxxxxxx
1


 
1
returnEither("abc").left.map(x => println(x))


It will print java.lang.NumberFormatException: For input string: "abc".

Using Match case with Either

Scala
 




xxxxxxxxxx
1


 
1
 returnEither("1") match
2
  {
3
    case Right(value) => println(s"Right value: $value")
4
    case Left(ex: NumberFormatException) => println(ex)
5
  }


It will print Right value: 1

Extract value from Either

Let's say we want to extract left value from Either.

Scala
 




xxxxxxxxxx
1


 
1
  println(returnEither("abc").left)


will print LeftProjection(Left(java.lang.NumberFormatException: For input string: "abc"))

Scala
 




xxxxxxxxxx
1


 
1
  println(returnEither("1").left)


will print LeftProjection(Right(1))

Scala
 




xxxxxxxxxx
1


 
1
println(returnEither("abc").left.get)


will print java.lang.NumberFormatException: For input string: "abc".

Scala
 




xxxxxxxxxx
1


 
1
println(returnEither("1").left.get)


will print: Exception in thread "main" java.util.NoSuchElementException: Either.left.get on Right

Oops. It had the right value.

We can use getOrElse or fold for default value.

getOrElse

Scala
 




xxxxxxxxxx
1


 
1
println(returnEither("1").left.getOrElse(2)) // will print 2


fold

Scala
 




xxxxxxxxxx
1


 
1
  println(returnEither("1").fold(
2
    i => s"Found an exception: '$i'",
3
    b => s"Found int: '$b'"
4
  ))


will print Found int: '1'

Scala
 




xxxxxxxxxx
1


 
1
  println(returnEither("abc").fold(
2
    i => s"Found an exception: '$i'",
3
    b => s"Found int: '$b'"
4
  ))


will print Found an exception: 'java.lang.NumberFormatException: For input string: "abc"'

Check value is Left or Right

Scala
 




xxxxxxxxxx
1


 
1
  println(returnEither("abc").isLeft) //print true
2
  println(returnEither("1").isRight) // print true


Working with Lists using Either

Scala
 




xxxxxxxxxx
1
14
9


 
1
val list: List[Either[Int, String]] = List(Right("r1"), Left(0), Right("r2"), Left(10), Right("r3"), Left(100), Right("r4"))
2
val newList = list.map(_.map(_.toUpperCase)).map(y => y.left.map(_ * 20))
3
println(newList)


Will give List(Right(R1), Left(0), Right(R2), Left(200), Right(R3), Left(2000), Right(R4)).

Let's understand how. As we know Either is right bias so list.map(x => x.map(_.toUpperCase)), x will only have Right Values which will be converted to uppercase then as we have return type as List[Either[Int, String]] for list.map(_.map(_.toUpperCase)). y will have left and right values. All the left values will be multiplied by 20.

toRight

y.toRight(x) checks if value is empty it return Left(x) else Right(y).

Scala
 




xxxxxxxxxx
1


 
1
val ok: Either[Error, String] = Some("Yeah!").toRight(new Error("Error!"))
2
val error: Either[Error, String] = None.toRight(new Error("Error!"))
3
println(ok) // Right(Yeah!)
4
println(error) // Left(java.lang.Error: Error!)


toLeft

y.toLeft(x) checks if value is empty it return Right(x) else Left(y).

Scala
 




xxxxxxxxxx
1


 
1
val okLeft: Either[Error, String] = Some(new Error("Error!")).toLeft("Yeah!")
2
val errorLeft: Either[Error, String] = None.toLeft("Yeah!")
3
println(okLeft) // Left(java.lang.Error: Error!)
4
println(errorLeft) // Right(Yeah!)


There could be a situation where one function is called then another and then another is a chain and the exceptions are thrown freely. How do we track which function actually caused the exception?

Scala
 




x


 
1
val array: Array[Int] = Array(0,2)
2
def fetchElement(el: Int): Either[Exception, Int] =
3
 if (el < array.length ) Right(array(el))
4
 else Left(new ArrayIndexOutOfBoundsException("from function fetchElement"))
5

          
6
def reciprocal(i: Int): Either[Exception, Double] =
7
 if (i == 0) Left(new IllegalArgumentException("from function reciprocal"))
8
 else Right(1.0 / i)
9

          
10
def stringify(d: Double): String = d.toString
11

          
12
def callFunctions(s: String): Either[Exception, String] = fetchElement(s.toInt).flatMap(reciprocal).map(stringify)
13

          
14
callFunctions("3") match {
15
  case Left(_: ArrayIndexOutOfBoundsException) => println("Exception in fetchElement")
16
  case Left(_: IllegalArgumentException) => println("Exception in reciprocal")
17
  case Left(_) => println("got unknown exception")
18
  case Right(s) => println(s"Got reciprocal: $s")
19
}


will print Exception in fetchElement.

If call callFunctions("0") will print Exception in reciprocal

Thanks for reading!

Scala (programming language)

Published at DZone with permission of Jyoti Sachdeva. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Modernizing Apache Spark Applications With GenAI: Migrating From Java to Scala
  • Mastering Advanced Aggregations in Spark SQL
  • Thermometer Continuation in Scala
  • Deploying a Scala Play Application to Heroku: A Step-by-Step Guide

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook