Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
315 lines (281 sloc) 10.951 kb
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala
object Option {
import scala.language.implicitConversions
/** An implicit conversion that converts an option to an iterable value
*/
implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList
/** An Option factory which creates Some(x) if the argument is not null,
* and None if it is null.
*
* @param x the value
* @return Some(value) if value != null, None if value == null
*/
def apply[A](x: A): Option[A] = if (x == null) None else Some(x)
/** An Option factory which returns `None` in a manner consistent with
* the collections hierarchy.
*/
def empty[A] : Option[A] = None
}
/** Represents optional values. Instances of `Option`
* are either an instance of $some or the object $none.
*
* The most idiomatic way to use an $option instance is to treat it
* as a collection or monad and use `map`,`flatMap`, `filter`, or
* `foreach`:
*
* {{{
* val name: Option[String] = request getParameter "name"
* val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase }
* println(upper getOrElse "")
* }}}
*
* Note that this is equivalent to {{{
* val upper = for {
* name <- request getParameter "name"
* trimmed <- Some(name.trim)
* upper <- Some(trimmed.toUpperCase) if trimmed.length != 0
* } yield upper
* println(upper getOrElse "")
* }}}
*
* Because of how for comprehension works, if $none is returned
* from `request.getParameter`, the entire expression results in
* $none
*
* This allows for sophisticated chaining of $option values without
* having to check for the existence of a value.
*
* A less-idiomatic way to use $option values is via pattern matching: {{{
* val nameMaybe = request getParameter "name"
* nameMaybe match {
* case Some(name) =>
* println(name.trim.toUppercase)
* case None =>
* println("No name value")
* }
* }}}
*
* @note Many of the methods in here are duplicative with those
* in the Traversable hierarchy, but they are duplicated for a reason:
* the implicit conversion tends to leave one with an Iterable in
* situations where one could have retained an Option.
*
* @author Martin Odersky
* @author Matthias Zenger
* @version 1.1, 16/01/2007
* @define none `None`
* @define some [[scala.Some]]
* @define option [[scala.Option]]
* @define p `p`
* @define f `f`
* @define coll option
* @define Coll `Option`
* @define orderDependent
* @define orderDependentFold
* @define mayNotTerminateInf
* @define willNotTerminateInf
* @define collectExample
* @define undefinedorder
* @define thatinfo the class of the returned collection. In the standard library configuration, `That` is `Iterable[B]`
* @define bfinfo an implicit value of class `CanBuildFrom` which determines the result class `That` from the current
* representation type `Repr` and the new element type `B`.
*/
sealed abstract class Option[+A] extends Product with Serializable {
self =>
/** Returns true if the option is $none, false otherwise.
*/
def isEmpty: Boolean
/** Returns true if the option is an instance of $some, false otherwise.
*/
def isDefined: Boolean = !isEmpty
/** Returns the option's value.
* @note The option must be nonEmpty.
* @throws Predef.NoSuchElementException if the option is empty.
*/
def get: A
/** Returns the option's value if the option is nonempty, otherwise
* return the result of evaluating `default`.
*
* @param default the default expression.
*/
@inline final def getOrElse[B >: A](default: => B): B =
if (isEmpty) default else this.get
/** Returns the option's value if it is nonempty,
* or `null` if it is empty.
* Although the use of null is discouraged, code written to use
* $option must often interface with code that expects and returns nulls.
* @example {{{
* val initalText: Option[String] = getInitialText
* val textField = new JComponent(initalText.orNull,20)
* }}}
*/
@inline final def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse null
/** Returns a $some containing the result of applying $f to this $option's
* value if this $option is nonempty.
* Otherwise return $none.
*
* @note This is similar to `flatMap` except here,
* $f does not need to wrap its result in an $option.
*
* @param f the function to apply
* @see flatMap
* @see foreach
*/
@inline final def map[B](f: A => B): Option[B] =
if (isEmpty) None else Some(f(this.get))
/** Returns the result of applying $f to this $option's
* value if the $option is nonempty. Otherwise, evaluates
* expression `ifEmpty`.
*
* @note This is equivalent to `$option map f getOrElse ifEmpty`.
*
* @param ifEmpty the expression to evaluate if empty.
* @param f the function to apply if nonempty.
*/
@inline final def fold[B](ifEmpty: => B)(f: A => B): B =
if (isEmpty) ifEmpty else f(this.get)
/** Returns the result of applying $f to this $option's value if
* this $option is nonempty.
* Returns $none if this $option is empty.
* Slightly different from `map` in that $f is expected to
* return an $option (which could be $none).
*
* @param f the function to apply
* @see map
* @see foreach
*/
@inline final def flatMap[B](f: A => Option[B]): Option[B] =
if (isEmpty) None else f(this.get)
def flatten[B](implicit ev: A <:< Option[B]): Option[B] =
if (isEmpty) None else ev(this.get)
/** Returns this $option if it is nonempty '''and''' applying the predicate $p to
* this $option's value returns true. Otherwise, return $none.
*
* @param p the predicate used for testing.
*/
@inline final def filter(p: A => Boolean): Option[A] =
if (isEmpty || p(this.get)) this else None
/** Returns this $option if it is nonempty '''and''' applying the predicate $p to
* this $option's value returns false. Otherwise, return $none.
*
* @param p the predicate used for testing.
*/
@inline final def filterNot(p: A => Boolean): Option[A] =
if (isEmpty || !p(this.get)) this else None
/** Returns false if the option is $none, true otherwise.
* @note Implemented here to avoid the implicit conversion to Iterable.
*/
final def nonEmpty = isDefined
/** Necessary to keep $option from being implicitly converted to
* [[scala.collection.Iterable]] in `for` comprehensions.
*/
@inline final def withFilter(p: A => Boolean): WithFilter = new WithFilter(p)
/** We need a whole WithFilter class to honor the "doesn't create a new
* collection" contract even though it seems unlikely to matter much in a
* collection with max size 1.
*/
class WithFilter(p: A => Boolean) {
def map[B](f: A => B): Option[B] = self filter p map f
def flatMap[B](f: A => Option[B]): Option[B] = self filter p flatMap f
def foreach[U](f: A => U): Unit = self filter p foreach f
def withFilter(q: A => Boolean): WithFilter = new WithFilter(x => p(x) && q(x))
}
/** Returns true if this option is nonempty '''and''' the predicate
* $p returns true when applied to this $option's value.
* Otherwise, returns false.
*
* @param p the predicate to test
*/
@inline final def exists(p: A => Boolean): Boolean =
!isEmpty && p(this.get)
/** Returns true if this option is empty '''or''' the predicate
* $p returns true when applied to this $option's value.
*
* @param p the predicate to test
*/
@inline final def forall(p: A => Boolean): Boolean = isEmpty || p(this.get)
/** Apply the given procedure $f to the option's value,
* if it is nonempty. Otherwise, do nothing.
*
* @param f the procedure to apply.
* @see map
* @see flatMap
*/
@inline final def foreach[U](f: A => U) {
if (!isEmpty) f(this.get)
}
/** Returns a $some containing the result of
* applying `pf` to this $option's contained
* value, '''if''' this option is
* nonempty '''and''' `pf` is defined for that value.
* Returns $none otherwise.
*
* @param pf the partial function.
* @return the result of applying `pf` to this $option's
* value (if possible), or $none.
*/
@inline final def collect[B](pf: PartialFunction[A, B]): Option[B] =
if (!isEmpty && pf.isDefinedAt(this.get)) Some(pf(this.get)) else None
/** Returns this $option if it is nonempty,
* otherwise return the result of evaluating `alternative`.
* @param alternative the alternative expression.
*/
@inline final def orElse[B >: A](alternative: => Option[B]): Option[B] =
if (isEmpty) alternative else this
/** Returns a singleton iterator returning the $option's value
* if it is nonempty, or an empty iterator if the option is empty.
*/
def iterator: Iterator[A] =
if (isEmpty) collection.Iterator.empty else collection.Iterator.single(this.get)
/** Returns a singleton list containing the $option's value
* if it is nonempty, or the empty list if the $option is empty.
*/
def toList: List[A] =
if (isEmpty) List() else new ::(this.get, Nil)
/** Returns a [[scala.util.Left]] containing the given
* argument `left` if this $option is empty, or
* a [[scala.util.Right]] containing this $option's value if
* this is nonempty.
*
* @param left the expression to evaluate and return if this is empty
* @see toLeft
*/
@inline final def toRight[X](left: => X) =
if (isEmpty) Left(left) else Right(this.get)
/** Returns a [[scala.util.Right]] containing the given
* argument `right` if this is empty, or
* a [[scala.util.Left]] containing this $option's value
* if this $option is nonempty.
*
* @param right the expression to evaluate and return if this is empty
* @see toRight
*/
@inline final def toLeft[X](right: => X) =
if (isEmpty) Right(right) else Left(this.get)
}
/** Class `Some[A]` represents existing values of type
* `A`.
*
* @author Martin Odersky
* @version 1.0, 16/07/2003
*/
final case class Some[+A](x: A) extends Option[A] {
def isEmpty = false
def get = x
}
/** This case object represents non-existent values.
*
* @author Martin Odersky
* @version 1.0, 16/07/2003
*/
case object None extends Option[Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("None.get")
}
Jump to Line
Something went wrong with that request. Please try again.