Represents a value of one of two possible types (a disjoint union).
An instance of Either
is an instance of either scala.util.Left or scala.util.Right.
A common use of Either
is as an alternative to scala.Option for dealing
with possibly missing values. In this usage, scala.None is replaced
with a scala.util.Left which can contain useful information.
scala.util.Right takes the place of scala.Some. Convention dictates
that Left
is used for failure and Right
is used for success.
For example, you could use Either[String, Int]
to indicate whether a
received input is a String
or an Int
.
import scala.io.StdIn._
val in = readLine("Type Either a string or an Int: ")
val result: Either[String,Int] =
try Right(in.toInt)
catch {
case e: NumberFormatException => Left(in)
}
result match {
case Right(x) => s"You passed me the Int: $x, which I will increment. $x + 1 = ${x+1}"
case Left(x) => s"You passed me the String: $x"
}
Either
is right-biased, which means that Right
is assumed to be the default case to
operate on. If it is Left
, operations like map
and flatMap
return the Left
value unchanged:
def doubled(i: Int) = i * 2
Right(42).map(doubled) // Right(84)
Left(42).map(doubled) // Left(42)
Since Either
defines the methods map
and flatMap
, it can also be used in for comprehensions:
val right1 = Right(1) : Right[Double, Int]
val right2 = Right(2)
val right3 = Right(3)
val left23 = Left(23.0) : Left[Double, Int]
val left42 = Left(42.0)
for {
x <- right1
y <- right2
z <- right3
} yield x + y + z // Right(6)
for {
x <- right1
y <- right2
z <- left23
} yield x + y + z // Left(23.0)
for {
x <- right1
y <- left23
z <- right2
} yield x + y + z // Left(23.0)
// Guard expressions are not supported:
for {
i <- right1
if i > 0
} yield i
// error: value withFilter is not a member of Right[Double,Int]
// Similarly, refutable patterns are not supported:
for (x: Int <- right1) yield x
// error: value withFilter is not a member of Right[Double,Int]
Since for
comprehensions use map
and flatMap
, the types
of function parameters used in the expression must be inferred.
These types are constrained by the Either
values. In particular,
because of right-biasing, Left
values may require an explicit
type argument for type parameter B
, the right value. Otherwise,
it might be inferred as Nothing
.
for {
x <- left23
y <- right1
z <- left42 // type at this position: Either[Double, Nothing]
} yield x + y + z
// ^
// error: ambiguous reference to overloaded definition,
// both method + in class Int of type (x: Char)Int
// and method + in class Int of type (x: Byte)Int
// match argument types (Nothing)
for (x <- right2 ; y <- left23) yield x + y // Left(23.0)
for (x <- right2 ; y <- left42) yield x + y // error
for {
x <- right1
y <- left42 // type at this position: Either[Double, Nothing]
z <- left23
} yield x + y + z
// Left(42.0), but unexpectedly a `Either[Double,String]`
- Companion
- object
- Source
- Either.scala
Value members
Abstract methods
Returns true
if this is a Left
, false
otherwise.
Returns true
if this is a Left
, false
otherwise.
Left("tulip").isLeft // true
Right("venus fly-trap").isLeft // false
- Source
- Either.scala
Returns true
if this is a Right
, false
otherwise.
Returns true
if this is a Right
, false
otherwise.
Left("tulip").isRight // false
Right("venus fly-trap").isRight // true
- Source
- Either.scala
Concrete methods
Returns true
if this is a Right
and its value is equal to elem
(as determined by ==
),
returns false
otherwise.
Returns true
if this is a Right
and its value is equal to elem
(as determined by ==
),
returns false
otherwise.
// Returns true because value of Right is "something" which equals "something".
Right("something") contains "something"
// Returns false because value of Right is "something" which does not equal "anything".
Right("something") contains "anything"
// Returns false because it's not a Right value.
Left("something") contains "something"
- Value Params
- elem
the element to test.
- Returns
true
if this is aRight
value equal toelem
.- Source
- Either.scala
Returns false
if Left
or returns the result of the application of
the given predicate to the Right
value.
Returns false
if Left
or returns the result of the application of
the given predicate to the Right
value.
Right(12).exists(_ > 10) // true
Right(7).exists(_ > 10) // false
Left(12).exists(_ => true) // false
- Source
- Either.scala
Returns Right
with the existing value of Right
if this is a Right
and the given predicate p
holds for the right value,
or Left(zero)
if this is a Right
and the given predicate p
does not hold for the right value,
or Left
with the existing value of Left
if this is a Left
.
Returns Right
with the existing value of Right
if this is a Right
and the given predicate p
holds for the right value,
or Left(zero)
if this is a Right
and the given predicate p
does not hold for the right value,
or Left
with the existing value of Left
if this is a Left
.
Right(12).filterOrElse(_ > 10, -1) // Right(12)
Right(7).filterOrElse(_ > 10, -1) // Left(-1)
Left(7).filterOrElse(_ => false, -1) // Left(7)
- Source
- Either.scala
Binds the given function across Right
.
Binds the given function across Right
.
- Value Params
- f
The function to bind across
Right
.
- Source
- Either.scala
Returns the right value if this is right or this value if this is left
Returns the right value if this is right or this value if this is left
- Example
val l: Either[String, Either[String, Int]] = Left("pancake") val rl: Either[String, Either[String, Int]] = Right(Left("flounder")) val rr: Either[String, Either[String, Int]] = Right(Right(7)) l.flatten //Either[String, Int]: Left("pancake") rl.flatten //Either[String, Int]: Left("flounder") rr.flatten //Either[String, Int]: Right(7)
Equivalent to
flatMap(id => id)
- Source
- Either.scala
Applies fa
if this is a Left
or fb
if this is a Right
.
Applies fa
if this is a Left
or fb
if this is a Right
.
- Value Params
- fa
the function to apply if this is a
Left
- fb
the function to apply if this is a
Right
- Returns
the results of applying the function
- Example
val result = util.Try("42".toInt).toEither result.fold( e => s"Operation failed with $e", v => s"Operation produced value: $v" )
- Source
- Either.scala
Returns true
if Left
or returns the result of the application of
the given predicate to the Right
value.
Returns true
if Left
or returns the result of the application of
the given predicate to the Right
value.
Right(12).forall(_ > 10) // true
Right(7).forall(_ > 10) // false
Left(12).forall(_ => false) // true
- Source
- Either.scala
Executes the given side-effecting function if this is a Right
.
Executes the given side-effecting function if this is a Right
.
Right(12).foreach(println) // prints "12"
Left(12).foreach(println) // doesn't print
- Value Params
- f
The side-effecting function to execute.
- Source
- Either.scala
Returns the value from this Right
or the given argument if this is a Left
.
Returns the value from this Right
or the given argument if this is a Left
.
Right(12).getOrElse(17) // 12
Left(12).getOrElse(17) // 17
- Source
- Either.scala
Joins an Either
through Left
.
Joins an Either
through Left
.
This method requires that the left side of this Either
is itself an
Either
type. That is, this must be some type like:
Either[Either[C, B], B]
(which respects the type parameter bounds, shown below.)
If this instance is a Left[Either[C, B]]
then the contained Either[C, B]
will be returned, otherwise this value will be returned unmodified.
Left[Either[Int, String], String](Right("flower")).joinLeft // Result: Right("flower")
Left[Either[Int, String], String](Left(12)).joinLeft // Result: Left(12)
Right[Either[Int, String], String]("daisy").joinLeft // Result: Right("daisy")
This method, and joinRight
, are analogous to Option#flatten
.
- Source
- Either.scala
Joins an Either
through Right
.
Joins an Either
through Right
.
This method requires that the right side of this Either
is itself
an Either
type. That is, this must be some type like:
Either[A, Either[A, C]]
(which respects the type parameter bounds, shown below.)
If this instance is a Right[Either[A, C]]
then the contained Either[A, C]
will be returned, otherwise this value will be returned unmodified.
- Example
Right[String, Either[String, Int]](Right(12)).joinRight // Result: Right(12) Right[String, Either[String, Int]](Left("flower")).joinRight // Result: Left("flower") Left[String, Either[String, Int]]("flower").joinRight // Result: Left("flower")
This method, and
joinLeft
, are analogous toOption#flatten
- Source
- Either.scala
Projects this Either
as a Left
.
Projects this Either
as a Left
.
This allows for-comprehensions over the left side of Either
instances,
reversing Either
's usual right-bias.
For example
for (s <- Left("flower").left) yield s.length // Left(6)
Continuing the analogy with scala.Option, a LeftProjection
declares
that Left
should be analogous to Some
in some code.
// using Option
def interactWithDB(x: Query): Option[Result] =
try Some(getResultFromDatabase(x))
catch {
case _: SQLException => None
}
// this will only be executed if interactWithDB returns a Some
val report = for (result <- interactWithDB(someQuery)) yield generateReport(result)
report match {
case Some(r) => send(r)
case None => log("report not generated, not sure why...")
}
// using Either
def interactWithDB(x: Query): Either[Exception, Result] =
try Right(getResultFromDatabase(x))
catch {
case e: SQLException => Left(e)
}
// run a report only if interactWithDB returns a Right
val report = for (result <- interactWithDB(someQuery)) yield generateReport(result)
report match {
case Right(r) => send(r)
case Left(e) => log(s"report not generated, reason was $e")
}
// only report errors
for (e <- interactWithDB(someQuery).left) log(s"query failed, reason was $e")
- Source
- Either.scala
The given function is applied if this is a Right
.
The given function is applied if this is a Right
.
Right(12).map(x => "flower") // Result: Right("flower")
Left(12).map(x => "flower") // Result: Left(12)
- Source
- Either.scala
Returns this Right
or the given argument if this is a Left
.
Returns this Right
or the given argument if this is a Left
.
Right(1) orElse Left(2) // Right(1)
Left(1) orElse Left(2) // Left(2)
Left(1) orElse Left(2) orElse Right(3) // Right(3)
- Source
- Either.scala
If this is a Left
, then return the left value in Right
or vice versa.
If this is a Left
, then return the left value in Right
or vice versa.
- Example
val left: Either[String, Int] = Left("left") val right: Either[Int, String] = left.swap // Result: Right("left")
val right = Right(2) val left = Left(3) for { r1 <- right r2 <- left.swap } yield r1 * r2 // Right(6)
- Source
- Either.scala
Returns a Some
containing the Right
value
if it exists or a None
if this is a Left
.
Returns a Some
containing the Right
value
if it exists or a None
if this is a Left
.
Right(12).toOption // Some(12)
Left(12).toOption // None
- Source
- Either.scala
Returns a Seq
containing the Right
value if
it exists or an empty Seq
if this is a Left
.
Returns a Seq
containing the Right
value if
it exists or an empty Seq
if this is a Left
.
Right(12).toSeq // Seq(12)
Left(12).toSeq // Seq()
- Source
- Either.scala
Deprecated methods
Projects this Either
as a Right
.
Projects this Either
as a Right
.
Because Either
is right-biased, this method is not normally needed.
- Deprecated
- Source
- Either.scala
Inherited methods
A method that should be called from every well-designed equals method that is open to be overridden in a subclass.
A method that should be called from every well-designed equals method that is open to be overridden in a subclass. See Programming in Scala, Chapter 28 for discussion and design.
- Value Params
- that
the value being probed for possible equality
- Returns
true if this instance can possibly equal
that
, otherwise false- Inherited from
- Equals
- Source
- Equals.scala
The size of this product.
The size of this product.
- Returns
for a product
A(x1, ..., xk)
, returnsk
- Inherited from
- Product
- Source
- Product.scala
The nth element of this product, 0-based.
The nth element of this product, 0-based. In other words, for a
product A(x1, ..., xk)
, returns x(n+1)
where 0 <= n < k
.
- Value Params
- n
the index of the element to return
- Returns
the element
n
elements after the first element- Throws
- IndexOutOfBoundsException
if the
n
is out of range(n < 0 || n >= productArity).
- Inherited from
- Product
- Source
- Product.scala
The name of the nth element of this product, 0-based.
The name of the nth element of this product, 0-based. In the default implementation, an empty string.
- Value Params
- n
the index of the element name to return
- Returns
the name of the specified element
- Throws
- IndexOutOfBoundsException
if the
n
is out of range(n < 0 || n >= productArity).
- Inherited from
- Product
- Source
- Product.scala
An iterator over the names of all the elements of this product.
An iterator over the names of all the elements of this product.
- Inherited from
- Product
- Source
- Product.scala
An iterator over all the elements of this product.
An iterator over all the elements of this product.
- Returns
in the default implementation, an
Iterator[Any]
- Inherited from
- Product
- Source
- Product.scala
A string used in the toString
methods of derived classes.
A string used in the toString
methods of derived classes.
Implementations may override this method to prepend a string prefix
to the result of toString
methods.
- Returns
in the default implementation, the empty string
- Inherited from
- Product
- Source
- Product.scala