summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2010-09-01 14:17:56 +0000
committerLukas Rytz <lukas.rytz@epfl.ch>2010-09-01 14:17:56 +0000
commitcc81e9fea64083aaf26cdf6eae1fc3510e3aedaf (patch)
tree0fd36af9c6508462b361abdbd84f05bac5418b12
parentd7cc24bf7857ffe9e8dd51e2ac7f6254013c03b6 (diff)
downloadscala-cc81e9fea64083aaf26cdf6eae1fc3510e3aedaf.tar.gz
scala-cc81e9fea64083aaf26cdf6eae1fc3510e3aedaf.tar.bz2
scala-cc81e9fea64083aaf26cdf6eae1fc3510e3aedaf.zip
Merged revisions 22473,22711-22713 via svnmerge...
Merged revisions 22473,22711-22713 via svnmerge from https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r22473 | extempore | 2010-07-02 18:26:05 +0200 (Fri, 02 Jul 2010) | 1 line Option gets an empty factory like the collections. Closes #3414, no review. ........ r22711 | rytz | 2010-08-09 15:37:04 +0200 (Mon, 09 Aug 2010) | 1 line close #3709. no review. ........ r22712 | rytz | 2010-08-09 15:37:07 +0200 (Mon, 09 Aug 2010) | 1 line close #7226. Apply trees are never considered stable (why were they? applications to field getters are Select trees, not Apply). review by odersky. ........ r22713 | rytz | 2010-08-09 15:37:11 +0200 (Mon, 09 Aug 2010) | 1 line update doc of option. close #3737. ........
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala2
-rw-r--r--src/library/scala/Option.scala169
-rw-r--r--src/library/scala/collection/mutable/ResizableArray.scala2
-rw-r--r--test/files/run/t3726.check2
-rw-r--r--test/files/run/t3726.scala8
5 files changed, 134 insertions, 49 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index f21b1b20ff..3c77a9e4d3 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -85,8 +85,6 @@ abstract class TreeInfo {
tree.symbol.isStable && isPureExpr(qual)
case TypeApply(fn, _) =>
isPureExpr(fn)
- case Apply(fn, List()) =>
- isPureExpr(fn)
case Typed(expr, _) =>
isPureExpr(expr)
case Block(stats, expr) =>
diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala
index 8992024353..bd15c31609 100644
--- a/src/library/scala/Option.scala
+++ b/src/library/scala/Option.scala
@@ -6,91 +6,151 @@
** |/ **
\* */
-
-
package scala
-object Option
-{
+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,
+ /** 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
}
-/** 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>.
+/** 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")
+ * }
+ * }
+ * }}}
*
* @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`
*/
sealed abstract class Option[+A] extends Product {
self =>
- /** True if the option is the <code>None</code> value, false otherwise.
+ /** Returns true if the option is $none, false otherwise.
*/
def isEmpty: Boolean
- /** True if the option is a <code>Some</code>(...) false otherwise.
+ /** Returns true if the option is an instance of $some, false otherwise.
*/
def isDefined: Boolean = !isEmpty
- /** get the value of this option.
+ /** Returns the option's value.
* @note The option must be nonEmpty.
* @throws Predef.NoSuchElementException if the option is empty.
*/
def get: A
- /** If the option is nonempty return its value,
- * otherwise return the result of evaluating a default expression.
+ /** Returns the option's value if the option is nonempty, otherwise
+ * return the result of evaluating `default`.
*
* @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.
+ /** 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)
+ * }}}
*/
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>.
+ /** 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
*/
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.
+ /** 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
*/
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.
+ /** 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.
*/
def filter(p: A => Boolean): Option[A] =
if (isEmpty || p(this.get)) this else None
- /** Necessary to keep Option from being implicitly converted to
- * Iterable in for comprehensions.
+ /** Necessary to keep $option from being implicitly converted to
+ * [[scala.collection.Iterable]] in `for` comprehensions.
*/
def withFilter(p: A => Boolean): WithFilter = new WithFilter(p)
@@ -105,66 +165,83 @@ sealed abstract class Option[+A] extends Product {
def withFilter(q: A => Boolean): WithFilter = new WithFilter(x => p(x) && q(x))
}
- /** If the option is nonempty, p(value), otherwise false.
+ /** 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
*/
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.
+ /** 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
*/
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.
+ /** 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.
*/
def collect[B](pf: PartialFunction[A, 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.
+ /** Returns this $option if it is nonempty,
+ * otherwise return the result of evaluating `alternative`.
+ * @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.
+ /** 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) 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.
+ /** 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 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.
+ /** Returns a [[scala.Left]] containing the given
+ * argument `left` if this $option is empty, or
+ * a [[scala.Right]] containing this $option's value if
+ * this is nonempty.
+ *
+ * @param left the expression to evaluate and return if this is empty
+ * @see toLeft
*/
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.
+ /** Returns a [[scala.Right]] containing the given
+ * argument `right` if this is empty, or
+ * a [[scala.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
*/
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>.
+/** Class `Some[A]` represents existing values of type
+ * `A`.
*
* @author Martin Odersky
* @version 1.0, 16/07/2003
diff --git a/src/library/scala/collection/mutable/ResizableArray.scala b/src/library/scala/collection/mutable/ResizableArray.scala
index 96ac7800ab..9cc19cd8e2 100644
--- a/src/library/scala/collection/mutable/ResizableArray.scala
+++ b/src/library/scala/collection/mutable/ResizableArray.scala
@@ -30,7 +30,7 @@ trait ResizableArray[A] extends IndexedSeq[A]
override def companion: GenericCompanion[ResizableArray] = ResizableArray
protected def initialSize: Int = 16
- protected var array: Array[AnyRef] = new Array[AnyRef](initialSize max 1)
+ protected var array: Array[AnyRef] = new Array[AnyRef](math.max(initialSize, 1))
protected var size0: Int = 0
diff --git a/test/files/run/t3726.check b/test/files/run/t3726.check
new file mode 100644
index 0000000000..7a5775bf34
--- /dev/null
+++ b/test/files/run/t3726.check
@@ -0,0 +1,2 @@
+hi there
+5 \ No newline at end of file
diff --git a/test/files/run/t3726.scala b/test/files/run/t3726.scala
new file mode 100644
index 0000000000..5ceed5416e
--- /dev/null
+++ b/test/files/run/t3726.scala
@@ -0,0 +1,8 @@
+object Test extends Application {
+ def test(f: () => Int) = {
+ val x = f()
+ 5
+ }
+
+ println(test(() => { println("hi there"); 0 }))
+}