Created
October 15, 2011 19:11
-
-
Save dwins/1290001 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** Represents a value of one of two possible types (a disjoint union.) | |
| * Instances of Either are either an instance of [[scala.Left]] or [[scala.Right]]. | |
| * | |
| * A common use of Either is as an alternative to [[scala.Option]] for dealing | |
| * with possible missing values. In this usage, [[scala.None]] is replaced | |
| * with a [[scala.Left]] which can contain useful information. | |
| * [[scala.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[Exception, Int]`` to safely parse a String: | |
| * | |
| * {{{ | |
| * val maybeAnInt = Console.readLine("Please enter your favorite integer: ") | |
| * val result: Either[Exception, Int] = | |
| * try { | |
| * Right(result.toInt) | |
| * } catch { | |
| * case ex => Left(ex) | |
| * } | |
| * println( | |
| * result.fold( | |
| * i => "So your favorite number is " + i + ", eh?", | |
| * ex => "That's not a number! It caused " + ex | |
| * ) | |
| * ) | |
| * }}} | |
| * | |
| * You can also use pattern matching to extract values from `Either`: {{{ | |
| * result match { | |
| * case Left(i) => | |
| * "So your favorite number is " + i + ", eh?" | |
| * case Right(i) => | |
| * "That's not a number! It caused " + ex | |
| * } | |
| * }}} | |
| * | |
| * For use with `for` comprehensions, an `Either` must be projected into | |
| * either its Left or Right value. A projection this way has `map` | |
| * defined to produce a modified copy of the original Either if the projection | |
| * corresponds to the proper either type: a left projection of a Right returns | |
| * the original value unmodified. | |
| * | |
| * {{{ | |
| * val l: Either[String, Int] = Left("scala") | |
| * val r: Either[String, Int] = Right(12) | |
| * l.left.map(_.size): Either[Int, Int] // Left(5) | |
| * r.left.map(_.size): Either[Int, Int] // Right(12) | |
| * l.right.map(_.toDouble): Either[String, Double] // Left("scala") | |
| * r.right.map(_.toDouble): Either[String, Double] // Right(12d) | |
| * }}} | |
| * | |
| * Of course, this works with for-comprehensions as well: {{{ | |
| * for (s <- l.left) yield s.size // Left(5) | |
| * }}} | |
| * | |
| * Projections define `flatMap` similarly, allowing "chaining" in | |
| * for-comprehensions with multiple scrutinees: {{{ | |
| * val l: Either[String, Int] = Left("scala") | |
| * val r: Either[String, Int] = Right(12) | |
| * l.left.flatMap(_ => r): Either[String, Int] // Right(12) | |
| * l.right.flatMap(_ => r): Either[String, Int] // Left("scala") | |
| * r.left.flatMap(_ => l): Either[String, Int] // Right(12) | |
| * r.right.flatMap(_ => l): Either[String, Int] // Left("scala") | |
| * }}} | |
| * | |
| * This also works with for-comprehensions: {{{ | |
| * for (s <- l.left; t <- r.left) yield i // Right(12) | |
| * }}} | |
| * | |
| * @author <a href="mailto:[email protected]">Tony Morris</a>, Workingmouse | |
| * @version 1.0, 11/10/2008 | |
| * @since 2.7 | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment