【scala原理系列】scala option原理示例源码分析

scala Option原理示例源码分析

原理

Scala的Option类型是受到Haskell语言中Maybe类型的启发而来。在函数式编程中,处理可能存在或不存在值的情况是一个常见的需求。Option提供了一种优雅的方式来表示这种情况,并且通过编译时类型检查来避免空指针异常

Option的基本原理如下:

  1. Option是一个容器类型,它可以包含一个值或者不包含任何值。
  2. Option有两个子类:Some和None。
    • Some表示Option中存在一个值,它将值封装在Some对象中。
    • None表示Option中不存在值,它是一个单例对象。
  3. 使用Option可以有效地避免使用null来表示缺少值的情况。null具有特殊含义,并且在使用过程中容易引发空指针异常。
  4. Option提供了一组方法来操作Option中的值:
    • getOrElse:获取Option中的值,如果不存在则返回默认值。
    • map:对Option中的值进行转换,返回新的Option。
    • flatMap:对Option中的值进行转换,返回新的Option,并且可以扁平化嵌套的Option结构。
    • filter:对Option中的值进行过滤,返回新的Option。
    • 等等。
  5. 使用Option可以使代码更加健壮和安全,因为它强制我们在处理可能不存在的值时进行明确的处理。

总结起来,Option的基本原理是通过Some和None来表示可能存在或不存在的值,避免了使用null并提供了一组方法来操作Option中的值。这种方式能够增加代码的可读性、可靠性和安全性,减少空指针异常的风险。

方法总结

以下是Option常用方法的总结:

  • isEmpty:判断Option是否为None。
  • isDefined:判断Option是否为Some。
  • get:获取Option中的值,如果Option为None,则抛出NoSuchElementException异常。
  • getOrElse:获取Option中的值,如果Option为None,则返回提供的默认值。
  • orElse:返回当前Option对象,如果Option为None,则返回提供的备选Option对象。
  • map:对Option中的值进行映射操作,并返回新的Option。如果Option为None,则直接返回None;如果Option为Some,则将映射函数应用于值并包装成Some返回。
  • flatMap:对Option中的值进行映射操作,并返回新的Option,可以扁平化嵌套的Option结构。如果Option为None,则直接返回None;如果Option为Some,则将映射函数应用于值并返回结果Option。
  • filter:根据给定的条件对Option中的值进行过滤,并返回新的Option。如果Option为None或不满足条件,则直接返回None;如果Option为Some且满足条件,则返回原始Some。
  • foreach:对Option中的值应用指定的函数。如果Option为Some,则将函数应用于值;如果Option为None,则不执行任何操作。
  • fold:将Option分为两种情况处理,根据Option是否为空来执行不同的操作。如果Option为None,则返回提供的默认值;如果Option为Some,则将值应用于给定的函数。
  • contains:判断Option中是否包含给定的元素。如果Option为Some且与给定元素相等,则返回true;否则返回false。
  • exists:判断Option中的值是否满足给定的条件。如果Option为Some且满足条件,则返回true;否则返回false。
  • forall:判断Option中的值是否都满足给定的条件。如果Option为None,则直接返回true;如果Option为Some且所有值都满足条件,则返回true;否则返回false。

这些方法可以帮助我们更方便、安全地处理可能为空的值,避免了空指针异常,并提供了一些常用的操作和转换方式。使用Option能够使代码更加健壮、可读性更高,并提高程序的安全性。

示例

以下是对每个Option方法的示例代码:

// Option对象示例
val option: Option[Int] = Some(10)
val noneOption: Option[Int] = None

// isEmpty和isDefined
println(option.isEmpty)    // false
println(option.isDefined)  // true

println(noneOption.isEmpty)    // true
println(noneOption.isDefined)  // false

// get
println(option.get)  // 10
// println(noneOption.get)  // 抛出NoSuchElementException异常

// getOrElse
val result1 = option.getOrElse(0)   // 10
val result2 = noneOption.getOrElse(0)   // 0
println(result1)
println(result2)

// orElse
val altOption = Some(20)
val mergedOption = noneOption.orElse(altOption)  // Some(20)
println(mergedOption)

// map
val mappedOption = option.map(_ * 2)  // Some(20)
val noneMappedOption = noneOption.map(_ * 2)  // None
println(mappedOption)
println(noneMappedOption)

// flatMap
val flatMappedOption = option.flatMap(x => if (x > 5) Some(x * 2) else None)  // Some(20)
val noneFlatMappedOption = noneOption.flatMap(x => if (x > 5) Some(x * 2) else None)  // None
println(flatMappedOption)
println(noneFlatMappedOption)

// filter
val filteredOption = option.filter(_ > 5)  // Some(10)
val noneFilteredOption = option.filter(_ > 15)  // None
println(filteredOption)
println(noneFilteredOption)

// foreach
option.foreach(x => println(x))  // 输出:10

// fold
val foldedResult1 = option.fold(0)(_ * 2)  // 20
val foldedResult2 = noneOption.fold(0)(_ * 2)  // 0
println(foldedResult1)
println(foldedResult2)

// contains
val isContained1 = option.contains(10)  // true
val isContained2 = option.contains(15)  // false
println(isContained1)
println(isContained2)

// exists
val doesExist1 = option.exists(_ > 5)  // true
val doesExist2 = option.exists(_ > 15)  // false
println(doesExist1)
println(doesExist2)

// forall
val forAll1 = option.forall(_ > 5)  // true
val forAll2 = option.forall(_ > 15)  // false
println(forAll1)
println(forAll2)

中文源码

1.object Option

object Option {

  import scala.language.implicitConversions

  /** 
   * 将 Option 转换为可迭代的值的隐式转换函数
   */
  implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList

  /** 
   * 如果参数不为 null,则返回 Some(x);如果为 null,则返回 None。
   *
   * @param  x 值
   * @return   如果 value != null,则返回 Some(value),否则返回 None
   */
  def apply[A](x: A): Option[A] = if (x == null) None else Some(x)

  /** 
   * 返回一个与集合层次结构一致的空 Option 对象 None。
   */
  def empty[A] : Option[A] = None
}

这段代码是 Scala 标准库中的 Option 对象的定义。Option 是一种表示可能存在或不存在值的容器类型。它有两个子类:Some 表示存在一个值,None 表示不存在值。

这段代码中定义了一个 Option 的伴生对象 Option,其中包含了一些方法和隐式转换。

  1. 隐式转换 option2Iterable
    这个隐式转换允许将 Option[A] 类型的对象转换为 Iterable[A] 类型的对象。它的实现通过调用 xo.toListOption 转换为 List,然后再将 List 转换为 Iterable
  2. apply 方法:
    这是一个工厂方法,用于创建 Option 对象。如果参数 x 不为 null,则返回 Some(x);如果 xnull,则返回 None
  3. empty 方法:
    这是一个工厂方法,返回一个空的 Option 对象,即 None

2. class Option[+A]

/** 表示可选值的类。`Option` 的实例要么是 `Some` 的实例,要么是 `None` 对象。
 *
 * 使用 `Option` 实例最常见的方式是将其视为集合或单子,并使用 `map`、`flatMap`、`filter` 或 `foreach` 等方法进行操作:
 *
 * {{{
 * val name: Option[String] = request getParameter "name"
 * val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase }
 * println(upper getOrElse "")
 * }}}
 *
 * 注意,这与以下代码是等价的:
 *
 * {{{
 * val upper = for {
 *   name <- request getParameter "name"
 *   trimmed <- Some(name.trim)
 *   upper <- Some(trimmed.toUpperCase) if trimmed.length != 0
 * } yield upper
 * println(upper getOrElse "")
 * }}}
 *
 * 因为 `for` 推导式的工作原理,如果 `request.getParameter` 返回 `None`,整个表达式结果将是 `None`。
 *
 * 这样可以方便地链式处理 `Option` 值,而不必检查是否存在值。
 *
 * 另一种使用 `Option` 值的方法是通过模式匹配:
 *
 * {{{
 * val nameMaybe = request getParameter "name"
 * nameMaybe match {
 *   case Some(name) =>
 *     println(name.trim.toUppercase)
 *   case None =>
 *     println("No name value")
 * }
 * }}}
 *
 * 注意:这里的许多方法与 Traversable 层次结构中的方法重复,但出于以下原因而重复:隐式转换往往会将可选值转换为可迭代对象(Iterable),但我们可能更希望保留 `Option` 值。
 *
 * 作者:Martin Odersky、Matthias Zenger
 * 版本:1.1,16/01/2007
 */
@SerialVersionUID(-114498752079829388L)
sealed abstract class Option[+A] extends Product with Serializable {
  self =>

  // 判断选项是否为空
  def isEmpty: Boolean

  // 判断选项是否为定义(非空)
  def isDefined: Boolean = !isEmpty

  // 获取选项的值,如果选项为空则抛出异常
  def get: A

  // 获取选项的值,如果选项为空则返回默认值
  def getOrElse[B >: A](default: => B): B =
    if (isEmpty) default else this.get

  // 将选项转换为 null 或者选项的值
  def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse ev(null)

  // 将选项的值应用于函数,并返回新的选项
  def map[B](f: A => B): Option[B] =
    if (isEmpty) None else Some(f(this.get))

  // 对选项进行折叠操作,如果为空则返回 ifEmpty,否则返回 f 对选项的值应用的结果
  def fold[B](ifEmpty: => B)(f: A => B): B =
    if (isEmpty) ifEmpty else f(this.get)

  // 对选项的值应用一个返回选项的函数,并返回新的选项
  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)

  // 根据给定的条件对选项进行过滤,返回符合条件的选项
  def filter(p: A => Boolean): Option[A] =
    if (isEmpty || p(this.get)) this else None

  // 根据给定的条件对选项进行过滤,返回不符合条件的选项
  def filterNot(p: A => Boolean): Option[A] =
    if (isEmpty || !p(this.get)) this else None

  final def nonEmpty = isDefined

  // 过滤器方法,用于支持 for 推导式中的条件过滤
  final def withFilter(p: A => Boolean): WithFilter = new WithFilter(p)

  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))
  }

  // 判断选项是否包含给定的元素
  final def contains[A1 >: A](elem: A1): Boolean =
    !isEmpty && this.get == elem

  // 判断选项的值是否满足给定的条件
  final def exists(p: A => Boolean): Boolean =
    !isEmpty && p(this.get)

  // 判断选项的值是否都满足给定的条件
  final def forall(p: A => Boolean): Boolean = isEmpty || p(this.get)

  // 对选项的值应用一个函数
  final def foreach[U](f: A => U) {
    if (!isEmpty) f(this.get)
  }

  // 根据偏函数对选项进行收集,返回新的选项
  final def collect[B](pf: PartialFunction[A, B]): Option[B] =
    if (!isEmpty) pf.lift(this.get) else None

  // 返回当前选项或替代选项,如果为空则返回替代选项
  final def orElse[B >: A](alternative: => Option[B]): Option[B] =
    if (isEmpty) alternative else this

  // 将选项转换为迭代器
  def iterator: Iterator[A] =
    if (isEmpty) collection.Iterator.empty else collection.Iterator.single(this.get)

  // 将选项转换为只包含选项值的单元素列表,如果选项非空则返回该列表,否则返回空列表
  def toList: List[A] =
    if (isEmpty) List() else new ::(this.get, Nil)

  // 如果选项为空,则返回一个包含给定参数 `left` 的 Left;如果选项非空,则返回一个包含选项值的 Right
  @inline final def toRight[X](left: => X) =
    if (isEmpty) Left(left) else Right(this.get)

  // 如果选项为空,则返回一个包含给定参数 `right` 的 Right;如果选项非空,则返回一个包含选项值的 Left
  @inline final def toLeft[X](right: => X) =
    if (isEmpty) Right(right) else Left(this.get)

这段代码定义了一个抽象类 Option[+A],它表示一个可能存在或不存在值的选项。这是一个用于处理可能存在或不存在值的选项的类。以下是它的一些重要方法:

  • isEmpty 方法返回一个布尔值,指示该选项是否为空。
  • isDefined 方法返回一个布尔值,指示该选项是否为定义(非空)。
  • get 方法返回选项的值。如果选项为空,则抛出 NoSuchElementException 异常。
  • getOrElse 方法返回选项的值,如果选项为空则返回默认值。
  • map 方法将一个函数应用于选项的值,并返回新的选项。
  • flatMap 方法将一个返回选项的函数应用于选项的值,并返回新的选项。
  • filter 方法根据给定的条件对选项进行过滤,返回符合条件的选项。
  • foreach 方法将一个函数应用于选项的值(如果非空)。
  • contains 方法检查选项是否包含给定的元素。
  • orElse 方法返回当前选项,如果为空,则返回替代选项。
  • toList 方法将选项转换为列表。

3.case class Some

Option 类提供了一种安全地处理可能为空的值的方式,可以避免空指针异常。它有两个子类:SomeNone,分别表示存在值。这段代码定义了 Option 对象的两个子类:SomeNone

/** Class `Some[A]` represents existing values of type
 *  `A`.
 *
 *  @author  Martin Odersky
 *  @version 1.0, 16/07/2003
 */
@SerialVersionUID(1234815782226070388L)
final case class Some[+A](x: A) extends Option[A] {
  def isEmpty = false
  def get = x
}
  • Some[A] 是一个表示存在值的类。它是 Option[A] 的子类。
  • xSome 类的一个字段,表示存在的值。
  • isEmpty 方法返回 false,表示该 Some 对象不为空。
  • get 方法返回存储的值 x

4.case object None

/** 这个案例对象表示不存在的值
 * 
 * 作者:Martin Odersky
 * 版本:1.0, 16/07/2003
 */
@SerialVersionUID(5066590221178148012L)
case object None extends Option[Nothing] {
  def isEmpty = true
  def get = throw new NoSuchElementException("None.get")
}
  • None 是一个表示不存在值的单例对象。它是 Option[Nothing] 的子类。
  • isEmpty 方法返回 true,表示该 None 对象为空。
  • get 方法抛出 NoSuchElementException 异常,因为 None 中没有存储任何值。

SomeNoneOption 类型的两种特殊情况,用于表示可能存在或不存在值的情况。Some 用于表示存在一个值,而 None 用于表示不存在值。通过使用这两个子类对象,可以更好地处理可能为空的值,并且可以在代码中进行模式匹配和安全访问。

英文源码

/*                     __                                               *\
**     ________ ___   / /  ___     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`.
 */
@SerialVersionUID(-114498752079829388L) // value computed by serialver for 2.11.2, annotation added in 2.11.4
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 java.util.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 initialText: Option[String] = getInitialText
   * val textField = new JComponent(initialText.orNull,20)
   * }}}
   */
  @inline final def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse ev(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))
  }

  /** Tests whether the option contains a given value as an element.
   *
   *  @example {{{
   *  // Returns true because Some instance contains string "something" which equals "something".
   *  Some("something") contains "something"
   *
   *  // Returns false because "something" != "anything".
   *  Some("something") contains "anything"
   *
   *  // Returns false when method called on None.
   *  None contains "anything"
   *  }}}
   *
   *  @param elem the element to test.
   *  @return `true` if the option has an element that is equal (as
   *  determined by `==`) to `elem`, `false` otherwise.
   */
  final def contains[A1 >: A](elem: A1): Boolean =
    !isEmpty && this.get == elem

  /** 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.
   *
   *  @example {{{
   *  // Returns Some(HTTP) because the partial function covers the case.
   *  Some("http") collect {case "http" => "HTTP"}
   *
   *  // Returns None because the partial function doesn't cover the case.
   *  Some("ftp") collect {case "http" => "HTTP"}
   *
   *  // Returns None because the option is empty. There is no value to pass to the partial function.
   *  None collect {case value => value}
   *  }}}
   *
   *  @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.lift(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
 */
@SerialVersionUID(1234815782226070388L) // value computed by serialver for 2.11.2, annotation added in 2.11.4
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
 */
@SerialVersionUID(5066590221178148012L) // value computed by serialver for 2.11.2, annotation added in 2.11.4
case object None extends Option[Nothing] {
  def isEmpty = true
  def get = throw new NoSuchElementException("None.get")
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BigDataMLApplication

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值