From 759c90dbc7c8361901ba6a4f193ab2ea3f76952b Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 14 Mar 2017 14:10:50 -0700 Subject: SI-10225 Either docs compile But without tut support, who knows. Boy scout aligns stars and updates several examples that didn't infer types in a way that compiles. --- src/library/scala/util/Either.scala | 590 +++++++++++++++++------------------- 1 file changed, 273 insertions(+), 317 deletions(-) (limited to 'src') diff --git a/src/library/scala/util/Either.scala b/src/library/scala/util/Either.scala index 523c10c483..4cc283c0cb 100644 --- a/src/library/scala/util/Either.scala +++ b/src/library/scala/util/Either.scala @@ -6,8 +6,6 @@ ** |/ ** \* */ - - package scala package util @@ -24,36 +22,36 @@ package util * received input is a String or an Int. * * {{{ - * val in = Console.readLine("Type Either 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: Exception => - * Left(in) - * } + * case e: Exception => Left(in) + * } * - * println(result match { + * 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, flatMap, ... return the Left value - * unchanged: + * operate on. If it is Left, operations like map, flatMap, ... return the Left value unchanged: * * {{{ - * Right(12).map(_ * 2) // Right(24) - * Left(23).map(_ * 2) // Left(23) + * def doubled(i: Int) = i * 2 + * Right(12).map(doubled) // Right(24) + * Left(23).map(doubled) // Left(23) * }}} * - * As Either defines the methods `map` and `flatMap`, it can also be used in for comprehensions: + * Since `Either` defines the methods `map` and `flatMap`, it can also be used in for comprehensions: * {{{ - * val right1: Right[Double, Int] = Right(1) - * val right2 = Right(2) - * val right3 = Right(3) - * val left23: Left[Double, Int] = Left(23.0) - * val left42 = Left(42.0) + * 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 { * a <- right1 @@ -92,77 +90,71 @@ package util * @since 2.7 */ sealed abstract class Either[+A, +B] extends Product with Serializable { - /** - * Projects this `Either` as a `Left`. - */ + /** Projects this `Either` as a `Left`. */ def left = Either.LeftProjection(this) - /** - * Projects this `Either` as a `Right`. + /** Projects this `Either` as a `Right`. * - * Because `Either` is right-biased, this method is not normally needed. - * (It is retained in the API for now for easy cross-compilation between Scala - * 2.11 and 2.12.) + * Because `Either` is right-biased, this method is not normally needed. + * (It is retained in the API for now for easy cross-compilation between Scala + * 2.11 and 2.12.) */ def right = Either.RightProjection(this) - /** - * 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`. * - * @example {{{ - * val result: Either[Exception, Value] = possiblyFailingOperation() - * log(result.fold( - * ex => s"Operation failed with $ex", - * v => s"Operation produced value: $v" - * )) - * }}} + * @example {{{ + * val result: Either[Exception, Value] = possiblyFailingOperation() + * result.fold( + * ex => s"Operation failed with $ex", + * v => s"Operation produced value: $v" + * ) + * }}} * - * @param fa the function to apply if this is a `Left` - * @param fb the function to apply if this is a `Right` - * @return the results of applying the function + * @param fa the function to apply if this is a `Left` + * @param fb the function to apply if this is a `Right` + * @return the results of applying the function */ def fold[C](fa: A => C, fb: B => C): C = this match { case Right(b) => fb(b) case Left(a) => fa(a) } - /** - * 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] = l.swap // Result: Right("left") - * }}} - * @example {{{ - * val right = Right(2) - * val left = Left(3) - * for { - * r1 <- right - * r2 <- left.swap - * } yield r1 * r2 // Right(6) - * }}} + * @example {{{ + * val left: Either[String, Int] = Left("left") + * val right: Either[Int, String] = left.swap // Result: Right("left") + * }}} + * @example {{{ + * val right = Right(2) + * val left = Left(3) + * for { + * r1 <- right + * r2 <- left.swap + * } yield r1 * r2 // Right(6) + * }}} */ def swap: Either[B, A] = this match { case Left(a) => Right(a) case Right(b) => Left(b) } - /** - * 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.) + * 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. + * 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") - * }}} + * @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 to `Option#flatten` */ @@ -172,51 +164,48 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { } - /** - * 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.) + * 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. + * 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") - * }}} + * {{{ + * 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` + * This method, and `joinRight`, are analogous to `Option#flatten`. */ def joinLeft[A1 >: A, B1 >: B, C](implicit ev: A1 <:< Either[C, B1]): Either[C, B1] = this match { case Left(a) => a case Right(b) => this.asInstanceOf[Either[C, B1]] } - /** - * 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(x => println(x)) // prints "12" - * Left(12).foreach(x => println(x)) // doesn't print - * }}} - * @param f The side-effecting function to execute. + * {{{ + * Right(12).foreach(x => println(x)) // prints "12" + * Left(12).foreach(x => println(x)) // doesn't print + * }}} + * @param f The side-effecting function to execute. */ def foreach[U](f: B => U): Unit = this match { case Right(b) => f(b) case Left(_) => } - /** - * 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 - * }}} + * {{{ + * Right(12).getOrElse(17) // 12 + * Left(12).getOrElse(17) // 17 + * }}} */ def getOrElse[BB >: B](or: => BB): BB = this match { case Right(b) => b @@ -245,53 +234,49 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { case Left(_) => false } - /** - * 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(_ > 10) // true - * }}} + * {{{ + * Right(12).forall(_ > 10) // true + * Right(7).forall(_ > 10) // false + * Left(12).forall((_: Int) > 10) // true + * }}} */ def forall(f: B => Boolean): Boolean = this match { case Right(b) => f(b) case Left(_) => true } - /** - * 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(_ > 10) // false - * }}} + * {{{ + * Right(12).exists(_ > 10) // true + * Right(7).exists(_ > 10) // false + * Left(12).exists((_: Int) > 10) // false + * }}} */ def exists(p: B => Boolean): Boolean = this match { case Right(b) => p(b) case Left(_) => false } - /** - * Binds the given function across `Right`. + /** Binds the given function across `Right`. * - * @param f The function to bind across `Right`. + * @param f The function to bind across `Right`. */ def flatMap[AA >: A, Y](f: B => Either[AA, Y]): Either[AA, Y] = this match { case Right(b) => f(b) case Left(a) => this.asInstanceOf[Either[AA, Y]] } - /** - * 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) - * }}} + * {{{ + * Right(12).map(x => "flower") // Result: Right("flower") + * Left(12).map(x => "flower") // Result: Left(12) + * }}} */ def map[Y](f: B => Y): Either[A, Y] = this match { case Right(b) => Right(f(b)) @@ -305,7 +290,7 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * {{{ * Right(12).filterOrElse(_ > 10, -1) // Right(12) * Right(7).filterOrElse(_ > 10, -1) // Left(-1) - * Left(12).filterOrElse(_ > 10, -1) // Left(12) + * Left(12).filterOrElse(_ => false, -1) // Left(12) * }}} */ def filterOrElse[AA >: A](p: B => Boolean, zero: => AA): Either[AA, B] = this match { @@ -344,32 +329,29 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { case Left(a) => Failure(a) } - /** - * 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 - * }}} + * {{{ + * Left("tulip").isLeft // true + * Right("venus fly-trap").isLeft // false + * }}} */ def isLeft: Boolean - /** - * 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 - * }}} + * {{{ + * Left("tulip").isRight // false + * Right("venus fly-trap").isRight // true + * }}} */ def isRight: Boolean } -/** - * The left side of the disjoint union, as opposed to the [[scala.util.Right]] side. +/** The left side of the disjoint union, as opposed to the [[scala.util.Right]] side. * - * @author Tony Morris, Workingmouse - * @version 1.0, 11/10/2008 + * @author Tony Morris, Workingmouse + * @version 1.0, 11/10/2008 */ final case class Left[+A, +B](@deprecatedName('a, "2.12.0") value: A) extends Either[A, B] { def isLeft = true @@ -378,11 +360,10 @@ final case class Left[+A, +B](@deprecatedName('a, "2.12.0") value: A) extends Ei @deprecated("Use .value instead.", "2.12.0") def a: A = value } -/** - * The right side of the disjoint union, as opposed to the [[scala.util.Left]] side. +/** The right side of the disjoint union, as opposed to the [[scala.util.Left]] side. * - * @author Tony Morris, Workingmouse - * @version 1.0, 11/10/2008 + * @author Tony Morris, Workingmouse + * @version 1.0, 11/10/2008 */ final case class Right[+A, +B](@deprecatedName('b, "2.12.0") value: B) extends Either[A, B] { def isLeft = false @@ -396,27 +377,26 @@ object Either { /** If the condition is satisfied, return the given `B` in `Right`, * otherwise, return the given `A` in `Left`. * - * {{{ - * val userInput: String = ... - * Either.cond( - * userInput.forall(_.isDigit) && userInput.size == 10, - * PhoneNumber(userInput), - * "The input (%s) does not look like a phone number".format(userInput) - * }}} + * {{{ + * val userInput: String = ... + * Either.cond( + * userInput.forall(_.isDigit) && userInput.size == 10, + * PhoneNumber(userInput), + * "The input (%s) does not look like a phone number".format(userInput) + * }}} */ def cond[X, Y](test: Boolean, right: => Y, left: => X): Either[X, Y] = if (test) Right(right) else Left(left) - /** - * Allows use of a `merge` method to extract values from Either instances - * regardless of whether they are Left or Right. + /** Allows use of a `merge` method to extract values from Either instances + * regardless of whether they are Left or Right. * - * {{{ - * val l = Left(List(1)): Either[List[Int], Vector[Int]] - * val r = Right(Vector(1)): Either[List[Int], Vector[Int]] - * l.merge: Seq[Int] // List(1) - * r.merge: Seq[Int] // Vector(1) - * }}} + * {{{ + * val l = Left(List(1)): Either[List[Int], Vector[Int]] + * val r = Right(Vector(1)): Either[List[Int], Vector[Int]] + * l.merge: Seq[Int] // List(1) + * r.merge: Seq[Int] // Vector(1) + * }}} */ implicit class MergeableEither[A](private val x: Either[A, A]) extends AnyVal { def merge: A = x match { @@ -425,62 +405,58 @@ object Either { } } - /** - * Projects an `Either` into a `Left`. + /** Projects an `Either` into a `Left`. * - * This allows for-comprehensions over the left side of Either instances, - * reversing Either's usual right-bias. + * 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. + * For example {{{ + * for (s <- Left("flower").left) yield s.length // Left(6) + * }}} * - * {{{ - * // using Option: - * def interactWithDB(x: Query): Option[Result] = - * try { - * Some(getResultFromDatabase(x)) - * } catch { - * case ex => None - * } - * - * // this will only be executed if interactWithDB returns a Some - * val report = - * for (r <- interactWithDB(someQuery)) yield generateReport(r) - * if (report.isDefined) - * send(report) - * else - * log("report not generated, not sure why...") - * }}} + * Continuing the analogy with [[scala.Option]], a `LeftProjection` declares + * that `Left` should be analogous to `Some` in some code. * - * {{{ - * // using Either - * 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) - * }}} + * {{{ + * // using Option: + * def interactWithDB(x: Query): Option[Result] = + * try { + * Some(getResultFromDatabase(x)) + * } catch { + * case ex => None + * } + * + * // this will only be executed if interactWithDB returns a Some + * val report = for (r <- interactWithDB(someQuery)) yield generateReport(r) + * if (report.isDefined) + * send(report) + * else + * log("report not generated, not sure why...") + * }}} * - * @author Tony Morris, Workingmouse - * @version 1.0, 11/10/2008 + * {{{ + * // using Either + * 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) + * }}} + * + * @author Tony Morris, Workingmouse + * @version 1.0, 11/10/2008 */ final case class LeftProjection[+A, +B](e: Either[A, B]) { - /** - * Returns the value from this `Left` or throws `java.util.NoSuchElementException` - * if this is a `Right`. + /** Returns the value from this `Left` or throws `java.util.NoSuchElementException` + * if this is a `Right`. * * {{{ * Left(12).left.get // 12 @@ -494,8 +470,7 @@ object Either { case Right(_) => throw new NoSuchElementException("Either.left.get on Right") } - /** - * Executes the given side-effecting function if this is a `Left`. + /** Executes the given side-effecting function if this is a `Left`. * * {{{ * Left(12).left.foreach(x => println(x)) // prints "12" @@ -508,116 +483,105 @@ object Either { case Right(_) => } - /** - * Returns the value from this `Left` or the given argument if this is a `Right`. - * - * {{{ - * Left(12).left.getOrElse(17) // 12 - * Right(12).left.getOrElse(17) // 17 - * }}} + /** Returns the value from this `Left` or the given argument if this is a `Right`. * + * {{{ + * Left(12).left.getOrElse(17) // 12 + * Right(12).left.getOrElse(17) // 17 + * }}} */ def getOrElse[AA >: A](or: => AA): AA = e match { case Left(a) => a case Right(_) => or } - /** - * Returns `true` if `Right` or returns the result of the application of - * the given function to the `Left` value. - * - * {{{ - * Left(12).left.forall(_ > 10) // true - * Left(7).left.forall(_ > 10) // false - * Right(12).left.forall(_ > 10) // true - * }}} + /** Returns `true` if `Right` or returns the result of the application of + * the given function to the `Left` value. * + * {{{ + * Left(12).left.forall(_ > 10) // true + * Left(7).left.forall(_ > 10) // false + * Right(12).left.forall(_ > 10) // true + * }}} */ def forall(@deprecatedName('f) p: A => Boolean): Boolean = e match { case Left(a) => p(a) case Right(_) => true } - /** - * Returns `false` if `Right` or returns the result of the application of - * the given function to the `Left` value. - * - * {{{ - * Left(12).left.exists(_ > 10) // true - * Left(7).left.exists(_ > 10) // false - * Right(12).left.exists(_ > 10) // false - * }}} + /** Returns `false` if `Right` or returns the result of the application of + * the given function to the `Left` value. * + * {{{ + * Left(12).left.exists(_ > 10) // true + * Left(7).left.exists(_ > 10) // false + * Right(12).left.exists(_ > 10) // false + * }}} */ def exists(@deprecatedName('f) p: A => Boolean): Boolean = e match { case Left(a) => p(a) case Right(_) => false } - /** - * Binds the given function across `Left`. + /** Binds the given function across `Left`. * - * {{{ - * Left(12).left.flatMap(x => Left("scala")) // Left("scala") - * Right(12).left.flatMap(x => Left("scala") // Right(12) - * }}} - * @param f The function to bind across `Left`. + * {{{ + * Left(12).left.flatMap(x => Left("scala")) // Left("scala") + * Right(12).left.flatMap(x => Left("scala")) // Right(12) + * }}} + * @param f The function to bind across `Left`. */ def flatMap[BB >: B, X](f: A => Either[X, BB]): Either[X, BB] = e match { case Left(a) => f(a) case Right(b) => e.asInstanceOf[Either[X, BB]] } - /** - * Maps the function argument through `Left`. + /** Maps the function argument through `Left`. * - * {{{ - * Left(12).left.map(_ + 2) // Left(14) - * Right[Int, Int](12).left.map(_ + 2) // Right(12) - * }}} + * {{{ + * Left(12).left.map(_ + 2) // Left(14) + * Right[Int, Int](12).left.map(_ + 2) // Right(12) + * }}} */ def map[X](f: A => X): Either[X, B] = e match { case Left(a) => Left(f(a)) case Right(b) => e.asInstanceOf[Either[X, B]] } - /** - * Returns `None` if this is a `Right` or if the given predicate - * `p` does not hold for the left value, otherwise, returns a `Left`. + /** Returns `None` if this is a `Right` or if the given predicate + * `p` does not hold for the left value, otherwise, returns a `Left`. * - * {{{ - * Left(12).left.filter(_ > 10) // Some(Left(12)) - * Left(7).left.filter(_ > 10) // None - * Right(12).left.filter(_ > 10) // None - * }}} + * {{{ + * Left(12).left.filter(_ > 10) // Some(Left(12)) + * Left(7).left.filter(_ > 10) // None + * Right(12).left.filter(_ > 10) // None + * }}} */ def filter[Y](p: A => Boolean): Option[Either[A, Y]] = e match { case Left(a) => if(p(a)) Some(Left(a)) else None case Right(b) => None } - /** - * Returns a `Seq` containing the `Left` value if it exists or an empty - * `Seq` if this is a `Right`. + /** Returns a `Seq` containing the `Left` value if it exists or an empty + * `Seq` if this is a `Right`. * - * {{{ - * Left(12).left.toSeq // Seq(12) - * Right(12).left.toSeq // Seq() - * }}} + * {{{ + * Left(12).left.toSeq // Seq(12) + * Right(12).left.toSeq // Seq() + * }}} */ def toSeq: Seq[A] = e match { case Left(a) => Seq(a) case Right(_) => Seq.empty } - /** - * Returns a `Some` containing the `Left` value if it exists or a - * `None` if this is a `Right`. + /** Returns a `Some` containing the `Left` value if it exists or a + * `None` if this is a `Right`. * - * {{{ - * Left(12).left.toOption // Some(12) - * Right(12).left.toOption // None - * }}} + * {{{ + * Left(12).left.toOption // Some(12) + * Right(12).left.toOption // None + * }}} */ def toOption: Option[A] = e match { case Left(a) => Some(a) @@ -625,26 +589,24 @@ object Either { } } - /** - * Projects an `Either` into a `Right`. + /** Projects an `Either` into a `Right`. * - * Because `Either` is already right-biased, this class is not normally needed. - * (It is retained in the library for now for easy cross-compilation between Scala - * 2.11 and 2.12.) + * Because `Either` is already right-biased, this class is not normally needed. + * (It is retained in the library for now for easy cross-compilation between Scala + * 2.11 and 2.12.) * - * @author Tony Morris, Workingmouse - * @version 1.0, 11/10/2008 + * @author Tony Morris, Workingmouse + * @version 1.0, 11/10/2008 */ final case class RightProjection[+A, +B](e: Either[A, B]) { - /** - * Returns the value from this `Right` or throws - * `java.util.NoSuchElementException` if this is a `Left`. + /** Returns the value from this `Right` or throws + * `java.util.NoSuchElementException` if this is a `Left`. * - * {{{ - * Right(12).right.get // 12 - * Left(12).right.get // NoSuchElementException - * }}} + * {{{ + * Right(12).right.get // 12 + * Left(12).right.get // NoSuchElementException + * }}} * * @throws java.util.NoSuchElementException if the projection is `Left`. */ @@ -653,80 +615,74 @@ object Either { case Left(_) => throw new NoSuchElementException("Either.right.get on Left") } - /** - * Executes the given side-effecting function if this is a `Right`. + /** Executes the given side-effecting function if this is a `Right`. * - * {{{ - * Right(12).right.foreach(x => println(x)) // prints "12" - * Left(12).right.foreach(x => println(x)) // doesn't print - * }}} - * @param f The side-effecting function to execute. + * {{{ + * Right(12).right.foreach(x => println(x)) // prints "12" + * Left(12).right.foreach(x => println(x)) // doesn't print + * }}} + * @param f The side-effecting function to execute. */ def foreach[U](f: B => U): Unit = e match { case Right(b) => f(b) case Left(_) => } - /** - * 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).right.getOrElse(17) // 12 - * Left(12).right.getOrElse(17) // 17 - * }}} + * {{{ + * Right(12).right.getOrElse(17) // 12 + * Left(12).right.getOrElse(17) // 17 + * }}} */ def getOrElse[BB >: B](or: => BB): BB = e match { case Right(b) => b case Left(_) => or } - /** - * Returns `true` if `Left` or returns the result of the application of - * the given function to the `Right` value. + /** Returns `true` if `Left` or returns the result of the application of + * the given function to the `Right` value. * - * {{{ - * Right(12).right.forall(_ > 10) // true - * Right(7).right.forall(_ > 10) // false - * Left(12).right.forall(_ > 10) // true - * }}} + * {{{ + * Right(12).right.forall(_ > 10) // true + * Right(7).right.forall(_ > 10) // false + * Left(12).right.forall(_ > 10) // true + * }}} */ def forall(f: B => Boolean): Boolean = e match { case Right(b) => f(b) case Left(_) => true } - /** - * Returns `false` if `Left` or returns the result of the application of - * the given function to the `Right` value. + /** Returns `false` if `Left` or returns the result of the application of + * the given function to the `Right` value. * - * {{{ - * Right(12).right.exists(_ > 10) // true - * Right(7).right.exists(_ > 10) // false - * Left(12).right.exists(_ > 10) // false - * }}} + * {{{ + * Right(12).right.exists(_ > 10) // true + * Right(7).right.exists(_ > 10) // false + * Left(12).right.exists(_ > 10) // false + * }}} */ def exists(@deprecatedName('f) p: B => Boolean): Boolean = e match { case Right(b) => p(b) case Left(_) => false } - /** - * Binds the given function across `Right`. + /** Binds the given function across `Right`. * - * @param f The function to bind across `Right`. + * @param f The function to bind across `Right`. */ def flatMap[AA >: A, Y](f: B => Either[AA, Y]): Either[AA, Y] = e match { case Right(b) => f(b) case Left(a) => e.asInstanceOf[Either[AA, Y]] } - /** - * The given function is applied if this is a `Right`. + /** The given function is applied if this is a `Right`. * - * {{{ - * Right(12).right.map(x => "flower") // Result: Right("flower") - * Left(12).right.map(x => "flower") // Result: Left(12) - * }}} + * {{{ + * Right(12).right.map(x => "flower") // Result: Right("flower") + * Left(12).right.map(x => "flower") // Result: Left(12) + * }}} */ def map[Y](f: B => Y): Either[A, Y] = e match { case Right(b) => Right(f(b)) -- cgit v1.2.3 From c636729b5f0b3b4811a7d7587fc49c5ca93bf563 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 21 Mar 2017 23:20:48 -0700 Subject: SI-10225 Either evinces good style Per Seth. --- src/library/scala/util/Either.scala | 112 +++++++++++++++++------------------- 1 file changed, 54 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/library/scala/util/Either.scala b/src/library/scala/util/Either.scala index 4cc283c0cb..d295478698 100644 --- a/src/library/scala/util/Either.scala +++ b/src/library/scala/util/Either.scala @@ -10,24 +10,24 @@ package scala package util /** Represents a value of one of two possible types (a disjoint union.) - * An instance of Either is either an instance of [[scala.util.Left]] or [[scala.util.Right]]. + * 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 possible missing values. In this usage, [[scala.None]] is replaced + * 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. + * that `Left` is used for failure and `Right` is used for success. * - * For example, you could use `Either[String, Int]` to detect whether a - * received input is a String or an Int. + * 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: Exception => Left(in) + * val result: Either[String,Int] = + * try Right(in.toInt) + * catch { + * case e: NumberFormatException => Left(in) * } * * result match { @@ -36,13 +36,13 @@ package util * } * }}} * - * 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, flatMap, ... return the Left value unchanged: + * `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(12).map(doubled) // Right(24) - * Left(23).map(doubled) // Left(23) + * 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: @@ -71,8 +71,9 @@ package util * c <- right2 * } yield a + b + c // Left(23.0) * - * // It is advisable to provide the type of the “missing” value (especially the right value for `Left`) - * // as otherwise that type might be inferred as `Nothing` without context: + * // It may be necessary to provide the type of the “missing” value, especially the type + * // of the right value for `Left`. Otherwise, without any context that constrains the type, + * // it might be inferred as `Nothing`: * for { * a <- left23 * b <- right1 @@ -96,18 +97,16 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { /** Projects this `Either` as a `Right`. * * Because `Either` is right-biased, this method is not normally needed. - * (It is retained in the API for now for easy cross-compilation between Scala - * 2.11 and 2.12.) */ def right = Either.RightProjection(this) /** Applies `fa` if this is a `Left` or `fb` if this is a `Right`. * * @example {{{ - * val result: Either[Exception, Value] = possiblyFailingOperation() + * val result = util.Try("42".toInt).toEither * result.fold( - * ex => s"Operation failed with $ex", - * v => s"Operation produced value: $v" + * e => s"Operation failed with $e", + * v => s"Operation produced value: $v" * ) * }}} * @@ -142,12 +141,12 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { /** 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: {{{ + * 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] + * 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 {{{ @@ -166,12 +165,12 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { /** 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: {{{ + * 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] + * 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. * * {{{ @@ -190,8 +189,8 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { /** Executes the given side-effecting function if this is a `Right`. * * {{{ - * Right(12).foreach(x => println(x)) // prints "12" - * Left(12).foreach(x => println(x)) // doesn't print + * Right(12).foreach(println) // prints "12" + * Left(12).foreach(println) // doesn't print * }}} * @param f The side-effecting function to execute. */ @@ -222,7 +221,7 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * // Returns false because value of Right is "something" which does not equal "anything". * Right("something") contains "anything" * - * // Returns false because there is no value for Right. + * // Returns false because it's not a Right value. * Left("something") contains "something" * }}} * @@ -238,9 +237,9 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * the given predicate to the `Right` value. * * {{{ - * Right(12).forall(_ > 10) // true - * Right(7).forall(_ > 10) // false - * Left(12).forall((_: Int) > 10) // true + * Right(12).forall(_ > 10) // true + * Right(7).forall(_ > 10) // false + * Left(12).forall(_ => false) // true * }}} */ def forall(f: B => Boolean): Boolean = this match { @@ -252,9 +251,9 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * the given predicate to the `Right` value. * * {{{ - * Right(12).exists(_ > 10) // true - * Right(7).exists(_ > 10) // false - * Left(12).exists((_: Int) > 10) // false + * Right(12).exists(_ > 10) // true + * Right(7).exists(_ > 10) // false + * Left(12).exists(_ => true) // false * }}} */ def exists(p: B => Boolean): Boolean = this match { @@ -288,9 +287,9 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * returns `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(12).filterOrElse(_ => false, -1) // Left(12) + * Right(12).filterOrElse(_ > 10, -1) // Right(12) + * Right(7).filterOrElse(_ > 10, -1) // Left(-1) + * Left(7).filterOrElse(_ => false, -1) // Left(7) * }}} */ def filterOrElse[AA >: A](p: B => Boolean, zero: => AA): Either[AA, B] = this match { @@ -420,35 +419,32 @@ object Either { * {{{ * // using Option: * def interactWithDB(x: Query): Option[Result] = - * try { - * Some(getResultFromDatabase(x)) - * } catch { - * case ex => None + * try Some(getResultFromDatabase(x)) + * catch { + * case _: SQLException => None * } * * // this will only be executed if interactWithDB returns a Some - * val report = for (r <- interactWithDB(someQuery)) yield generateReport(r) - * if (report.isDefined) - * send(report) - * else - * log("report not generated, not sure why...") + * 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 ex => Left(ex) + * try Right(getResultFromDatabase(x)) + * catch { + * case e: SQLException => Left(e) * } * * // 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) + * val report = for (result <- interactWithDB(someQuery).right) yield generateReport(result) + * report match { + * case Right(r) => send(r) + * case Left(e) => log(s"report not generated, reason was $e") + * } * }}} * * @author Tony Morris, Workingmouse @@ -459,7 +455,7 @@ object Either { * if this is a `Right`. * * {{{ - * Left(12).left.get // 12 + * Left(12).left.get // 12 * Right(12).left.get // NoSuchElementException * }}} * -- cgit v1.2.3