summaryrefslogtreecommitdiff
path: root/src/library/scala/Option.scala
blob: feacfd6acd3d84725f0a427d0a063da94ec80e48 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2002-2009, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id$


package scala

import annotation.experimental

object Option
{
  /** 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(value) 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
   */
  @experimental
  def apply[A](x: A): Option[A] = if (x == null) None else Some(x)
}

/** This class represents optional values. Instances of <code>Option</code>
 *  are either instances of case class <code>Some</code> or it is case
 *  object <code>None</code>.
 *
 *  @author  Martin Odersky
 *  @author  Matthias Zenger
 *  @version 1.1, 16/01/2007
 */
sealed abstract class Option[+A] extends Product {

  /** True if the option is the <code>None</code> value, false otherwise.
   */
  def isEmpty: Boolean

  /** True if the option is a <code>Some</code>(...) false otherwise.
   */
  def isDefined: Boolean = !isEmpty

  /** get the value of this option.
   *  @requires that the option is nonEmpty.
   *  @throws Predef.NoSuchElementException if the option is empty.
   */
  def get: A

  @deprecated("use <code>getOrElse</code> instead")
  def get[B >: A](default: B): B = this match {
    case None => default
    case Some(x) => x
  }

  /** If the option is nonempty return its value,
   *  otherwise return the result of evaluating a default expression.
   *
   *  @param default  the default expression.
   */
  def getOrElse[B >: A](default: => B): B =
    if (isEmpty) default else this.get

  /** The option's value if it is nonempty, or <code>null</code> if it is empty.
   *  The use of null of course is discouraged, but code written to use Options
   *  often must interface with code which expects and returns nulls.
   */
  @experimental
  def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse null

  /** If the option is nonempty, return a function applied to its value,
   *  wrapped in a Some i.e. <code>Some(f(this.get))</code>.
   *  Otherwise return <code>None</code>.
   *
   *  @param  f   the function to apply
   */
  def map[B](f: A => B): Option[B] =
    if (isEmpty) None else Some(f(this.get))

  /** If the option is nonempty, return a function applied to its value.
   *  Otherwise return None.
   *  @param  f   the function to apply
   */
  def flatMap[B](f: A => Option[B]): Option[B] =
    if (isEmpty) None else f(this.get)

  /** If the option is nonempty and the given predicate <code>p</code>
   *  yields <code>false</code> on its value, return <code>None</code>.
   *  Otherwise return the option value itself.
   *
   *  @param  p   the predicate used for testing.
   */
  def filter(p: A => Boolean): Option[A] =
    if (isEmpty || p(this.get)) this else None

  /** If the option is nonempty, p(value), otherwise false.
   *
   *  @param  p   the predicate to test
   */
  def exists(p: A => Boolean): Boolean =
    !isEmpty && p(this.get)

  /** Apply the given procedure <code>f</code> to the option's value,
   *  if it is nonempty. Do nothing if it is empty.
   *
   *  @param  f   the procedure to apply.
   */
  def foreach[U](f: A => U) {
    if (!isEmpty) f(this.get)
  }

  /** If the given partial function <code>pf</code> is defined for the
   *  option's value, apply it to the value.  Otherwise, None.
   *
   *  @param  pf   the partial function.
   */
  @experimental
  def partialMap[B](pf: PartialFunction[Any, B]): Option[B] =
    if (!isEmpty && pf.isDefinedAt(this.get)) Some(pf(this.get)) else None

  /** If the option is nonempty return it,
   *  otherwise return the result of evaluating an alternative expression.
   *  @param alternative  the alternative expression.
   */
  def orElse[B >: A](alternative: => Option[B]): Option[B] =
    if (isEmpty) alternative else this

  /** An singleton iterator returning the option's value if it is nonempty
   *  or the empty iterator if the option is empty.
   */
  def iterator: Iterator[A] =
    if (isEmpty) Iterator.empty else Iterator.single(this.get)

  /** 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 List(this.get)

  /** An <code>Either</code> that is a <code>Left</code> with the given argument
   * <code>left</code> if this is empty, or a <code>Right</code> if this is nonempty with the
   * option's value.
   */
  def toRight[X](left: => X) =
    if (isEmpty) Left(left) else Right(this.get)

  /** An <code>Either</code> that is a <code>Right</code> with the given argument
   * <code>right</code> if this is empty, or a <code>Left</code> if this is nonempty with the
   * option's value.
   */
  def toLeft[X](right: => X) =
    if (isEmpty) Right(right) else Left(this.get)
}

/** Class <code>Some[A]</code> represents existing values of type
 *  <code>A</code>.
 *
 *  @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")
}