From 1e88594f358d08b5e9b22ba87280003a581359e4 Mon Sep 17 00:00:00 2001
From: Martin Odersky $2"""),
+ ("""\{\{\{(.*(?:\n.*)*)\}\}\}""".r, """ "
+ if (firstParBreak == -1) firstParBreak = mainComment.length - 2
+ val comment = mainComment.substring(0, firstParBreak)+" "+
+ str.substring(skipLineLead(str, idx, str.length))+"*/"
+ val commentPos = subPos(offset + idx, offset + str.length)
+ UseCase(DocComment(comment, commentPos), code, codePos)
+ }
+
+ def defineVariables(sym: Symbol) {
+ for (str <- defines) {
+ val start = definePrefix.length
+ var idx = skipVariable(str, start)
+ val vble = variableName(str.substring(start, idx))
+ if (idx < str.length && (str charAt idx) == ' ') idx += 1
+ defs(sym) += vble -> str.substring(idx)
+ }
+ if (defs(sym).nonEmpty) println("vars of "+sym+" = "+defs(sym)) // !!!
+ }
+ }
+
+ case class UseCase(comment: DocComment, body: String, pos: Position) {
+ var defined: List[Symbol] = List()
+ var aliases: List[Symbol] = List()
+
+ def expandedDefs(site: Symbol): List[Symbol] = {
+
+ def select(site: Type, name: Name, orElse: => Type): Type = {
+ val member = site.nonPrivateMember(name)
+ if (member.isTerm) SingleType(site, member)
+ else if (member.isType) site.memberType(member)
+ else orElse
+ }
+
+ def getSite(name: Name): Type = {
+ if (name == nme.this_) site.thisType
+ else {
+ def findIn(sites: List[Symbol]): Type = sites match {
+ case List() => NoType
+ case site :: sites1 => select(site.thisType, name, findIn(sites1))
+ }
+ val (classes, pkgs) = site.ownerChain.span(!_.isPackageClass)
+ findIn(classes ::: List(pkgs.head, definitions.RootClass))
+ }
+ }
+
+ def getType(str: String): Type = {
+ val parts = str.split("""\.""").toList
+ val partnames = (parts.init map newTermName) ::: List(newTypeName(parts.last))
+ (getSite(partnames.head) /: partnames.tail)(select(_, _, NoType))
+ }
+
+ val aliasExpansions: List[Type] =
+ for (alias <- aliases) yield
+ lookupVariable(alias.name.toString.substring(1), site) match {
+ case Some(repl) =>
+ val tpe = getType(repl)
+ if (tpe != NoType) tpe
+ else {
+ val alias1 = alias.cloneSymbol(definitions.RootClass)
+ alias1.name = repl.toTypeName
+ TypeRef(NoPrefix, alias1, List())
+ }
+ case None =>
+ TypeRef(NoPrefix, alias, List())
+ }
+
+ def subst(sym: Symbol, from: List[Symbol], to: List[Type]): Type =
+ if (from.isEmpty) sym.tpe
+ else if (from.head == sym) to.head
+ else subst(sym, from.tail, to.tail)
+
+ val substAliases = new TypeMap {
+ def apply(tp: Type) = mapOver(tp) match {
+ case tp1 @ TypeRef(pre, sym, args) if (sym.name.length > 1 && sym.name(0) == '$') =>
+ subst(sym, aliases, aliasExpansions) match {
+ case TypeRef(pre, sym1, _) =>
+ TypeRef(pre, sym1, args)
+ case _ =>
+ tp1
+ }
+ case tp1 =>
+ tp1
+ }
+ }
+
+ for (defn <- defined) yield
+ defn.cloneSymbol(site).setInfo(
+ substAliases(defn.info).asSeenFrom(site.thisType, defn.owner))
+ }
+ }
+
+ class ExpansionLimitExceeded(str: String) extends Exception
+}
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index d18ecbbd37..4ba5f17a40 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -215,7 +215,7 @@ abstract class TreePrinters {
}
case DocDef(comment, definition) =>
- print(comment); println; print(definition)
+ print(comment.raw); println; print(definition)
case Template(parents, self, body) =>
val currentOwner1 = currentOwner
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 6c6311f143..3af729d4d7 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -570,7 +570,7 @@ trait Trees {
// It's used primarily as a marker to check that the import has been typechecked.
/** Documented definition, eliminated by analyzer */
- case class DocDef(comment: String, definition: Tree)
+ case class DocDef(comment: DocComment, definition: Tree)
extends Tree {
override def symbol: Symbol = definition.symbol
override def symbol_=(sym: Symbol) { definition.symbol = sym }
@@ -1072,7 +1072,7 @@ trait Trees {
def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef
def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef
def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import
- def DocDef(tree: Tree, comment: String, definition: Tree): DocDef
+ def DocDef(tree: Tree, comment: DocComment, definition: Tree): DocDef
def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template
def Block(tree: Tree, stats: List[Tree], expr: Tree): Block
def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef
@@ -1127,7 +1127,7 @@ trait Trees {
new LabelDef(name, params, rhs).copyAttrs(tree)
def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) =
new Import(expr, selectors).copyAttrs(tree)
- def DocDef(tree: Tree, comment: String, definition: Tree) =
+ def DocDef(tree: Tree, comment: DocComment, definition: Tree) =
new DocDef(comment, definition).copyAttrs(tree)
def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) =
new Template(parents, self, body).copyAttrs(tree)
@@ -1244,7 +1244,7 @@ trait Trees {
if (expr0 == expr) && (selectors0 == selectors) => t
case _ => treeCopy.Import(tree, expr, selectors)
}
- def DocDef(tree: Tree, comment: String, definition: Tree) = tree match {
+ def DocDef(tree: Tree, comment: DocComment, definition: Tree) = tree match {
case t @ DocDef(comment0, definition0)
if (comment0 == comment) && (definition0 == definition) => t
case _ => treeCopy.DocDef(tree, comment, definition)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index de71ba30ab..c4c26e54b3 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -420,13 +420,13 @@ self =>
*/
def joinComment(trees: => List[Tree]): List[Tree] = {
val doc = in.flushDoc
- if ((doc ne null) && doc._1.length > 0) {
+ if ((doc ne null) && doc.raw.length > 0) {
val ts = trees
val main = ts.find(_.pos.isOpaqueRange)
ts map {
t =>
- val dd = DocDef(doc._1, t)
- val pos = doc._2.withEnd(t.pos.endOrPoint)
+ val dd = DocDef(doc, t)
+ val pos = doc.pos.withEnd(t.pos.endOrPoint)
dd setPos (if (t eq main) pos else pos.makeTransparent)
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 62c47e8606..3de13ed877 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -103,11 +103,11 @@ trait Scanners {
/** buffer for the documentation comment
*/
var docBuffer: StringBuilder = null
- var docOffset: Position = null
+ var docPos: Position = null
/** Return current docBuffer and set docBuffer to null */
- def flushDoc = {
- val ret = if (docBuffer != null) (docBuffer.toString, docOffset) else null
+ def flushDoc: DocComment = {
+ val ret = if (docBuffer != null) DocComment(docBuffer.toString, docPos) else null
docBuffer = null
ret
}
@@ -1091,8 +1091,8 @@ trait Scanners {
}
override def foundDocComment(value: String, start: Int, end: Int) {
- docOffset = new RangePosition(unit.source, start, start, end)
- unit.comment(docOffset, value)
+ docPos = new RangePosition(unit.source, start, start, end)
+ unit.comment(docPos, value)
}
}
diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
index 240ba17d51..3c969c41f8 100644
--- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
@@ -39,7 +39,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
override def onlyPresentation = true
lazy val addSourceless = {
val sless = new SourcelessComments { val global = compiler }
- comments ++= sless.comments
+ docComments ++= sless.comments
}
}
diff --git a/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala b/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala
index 50888ba27c..9216fa6f23 100644
--- a/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala
+++ b/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala
@@ -21,9 +21,9 @@ abstract class SourcelessComments {
lazy val comments = {
- val comment = mutable.HashMap.empty[Symbol, String]
+ val comment = mutable.HashMap.empty[Symbol, DocComment]
- comment(NothingClass) = """
+ comment(NothingClass) = new DocComment("""
/**
* Class
* Class
* Class $1
"""),
+ ("""`([^`]*)`""" .r, """$1
"""),
+ ("""__([^_]*)__""" .r, """$1"""),
+ ("""''([^']*)''""" .r, """$1"""),
+ ("""'''([^']*)'''""" .r, """$1"""),
+ ("""\^([^^]*)\^""" .r, """$1"""),
+ (""",,([^,]*),,""" .r, """$1"""))
+ private def expandWiki(str: String): String =
+ (str /: wikiReplacements) { (str1, regexRepl) => regexRepl._1 replaceAllIn(str1, regexRepl._2) }
+
+ /** Lookup definition of variable.
+ *
+ * @param vble The variable for which a definition is searched
+ * @param owner The current owner in which variable definitions are searched.
+ * @param site The class for which doc comments are generated
+ */
+ def lookupVariable(vble: String, site: Symbol): Option[String] =
+ if (site == NoSymbol)
+ None
+ else
+ mapFind(site.info.baseClasses)(defs(_).get(vble)) match {
+ case None => lookupVariable(vble, site.owner)
+ case someStr => someStr
+ }
+
+ private var expandCount = 0
+ private final val expandLimit = 10
+
+ /** Expand variable occurrences in string `str', until a fix point is reached or
+ * a expandLimit is exceeded.
+ *
+ * @param str The string to be expanded
+ * @param site The class for which doc comments are generated
+ * @return Expanded string
+ */
+ private def expandVariables(str: String, site: Symbol): String =
+ if (expandCount < expandLimit) {
+ try {
+ val out = new StringBuilder
+ var start = 0
+ var idx = 0
+ while (idx < str.length) {
+ if ((str charAt idx) == '$') {
+ val vstart = idx
+ idx = skipVariable(str, idx + 1)
+ val vname = variableName(str.substring(vstart + 1, idx))
+ if (vname.length > 0) {
+ lookupVariable(vname, site) match {
+ case Some(replacement) =>
+ out append str.substring(start, vstart)
+ out append replacement
+ start = idx
+ case None =>
+ println("no replacement for "+vname) // !!!
+ }
+ } else {
+ idx += 1
+ }
+ } else {
+ idx += 1
+ }
+ }
+ if (out.length == 0) str
+ else {
+ out append str.substring(start)
+ expandVariables(out.toString, site)
+ }
+ } finally {
+ expandCount -= 1
+ }
+ } else throw new ExpansionLimitExceeded(str)
+
+ case class DocComment(raw: String, pos: Position = NoPosition) {
+
+ lazy val (template, defines, useCases) = {
+ val parts = decompose(raw)
+ val (defines, usecases) = parts.tail partition (_._1 startsWith definePrefix)
+ val templ = expandWiki(parts.head._1)
+ (templ,
+ defines map (d => expandWiki(d._1)),
+ usecases map (decomposeUseCase(_, templ)))
+ }
+
+ def expanded(site: Symbol): String =
+ expandVariables(template, site)
+/*
+ expansions get site match {
+ case Some(str) => str
+ case None => val str =
+ expandVariables(template, sym, site)
+ expansions += (site -> str)
+ str
+ }
+ private var expansions: Map[Symbol, String] = Map()
+*/
+
+
+ /** Decomposes a comment string into
+ * an initial comment and a list of @define and @usecase clauses, each with starting index
+ */
+ private def decompose(str: String): List[(String, Int)] = {
+ val out = new ListBuffer[(String, Int)]
+ var segstart = 0
+ var idx = 3 // skip initial "/**"
+ val end = str.length - 2 // stop before final "*/"
+ var eolIdx = idx
+ while (idx < end) {
+ if ((str charAt idx) == '\n') {
+ eolIdx = idx
+ idx = skipLineLead(str, idx, end)
+ if ((str charAt idx) == '@' &&
+ (str.startsWith(definePrefix, idx) || str.startsWith(usecasePrefix, idx))) {
+ var segment = str.substring(segstart, eolIdx)
+ if (segstart == 0) segment += "*/"
+ out += ((segment, segstart))
+ segstart = idx
+ }
+ } else idx += 1
+ }
+ if (segstart == 0)
+ List((str, 0))
+ else {
+ out += ((str.substring(segstart, eolIdx), segstart))
+ out.toList
+ }
+ }
+
+ def subPos(start: Int, end: Int) =
+ if (pos == NoPosition) NoPosition
+ else {
+ val start1 = pos.start + start
+ val end1 = pos.end + end
+ pos withStart start1 withPoint start1 withEnd end1
+ }
+
+ def decomposeUseCase(stroff: (String, Int), mainComment: String): UseCase = {
+ val str = stroff._1
+ val offset = stroff._2
+ val start = usecasePrefix.length
+ var idx = start
+ while (idx < str.length && (str charAt idx) != '\n') idx += 1
+ val code = str.substring(start, idx)
+ val codePos = subPos(offset + usecasePrefix.length, offset + idx)
+ var firstParBreak = mainComment indexOf "Nothing
is - together with class
* Null
- at the bottom of the
@@ -44,9 +44,9 @@ abstract class SourcelessComments {
* instance of List[T]
, for
* any element type T
.
* Null
is - together with class
* Nothing
- at the bottom of the
@@ -61,12 +61,12 @@ abstract class SourcelessComments {
* it is not possible to assign null
to a variable of
* type Int
.
* Any
is the root of the AnyRef
and
* AnyVal
.
* this
)
* with the argument object (arg0
) for equivalence.
*
@@ -113,34 +113,34 @@ abstract class SourcelessComments {
* @param arg0 the object to compare against this object for equality.
* @return true
if the receiver object is equivalent to the argument; false
otherwise.
*
* @param arg0 the object to compare against this object for equality. * @return `true` if the receiver object is equivalent to the argument; `false` otherwise. *
*/ - """ + """) - comment(Any_!=) = """ + comment(Any_!=) = new DocComment(""" /** `o != arg0` is the same as `!(o == (arg0))`. ** @param arg0 the object to compare against this object for dis-equality. * @return `false` if the receiver object is equivalent to the argument; `true` otherwise. *
*/ - """ + """) - comment(Any_toString) = """ + comment(Any_toString) = new DocComment(""" /** Returns a string representation of the object. ** The default representation is platform dependent. * * @return a string representation of the object. *
*/ - """ + """) - comment(Any_asInstanceOf) = """ + comment(Any_asInstanceOf) = new DocComment(""" /**This method is used to cast the receiver object to be of typeT0
.
*
* Note that the success of a cast at runtime is modulo Scala's
@@ -156,9 +156,9 @@ abstract class SourcelessComments {
* instance of erasure of type T0
.
* @return the receiver object.
*
T0
.
*
* Note that the test result of the test is modulo Scala's erasure
@@ -172,9 +172,9 @@ abstract class SourcelessComments {
*
* @return true
if the receiver object is an
* instance of erasure of type T0
; false
otherwise. */
- """
+ """)
- comment(Any_hashCode) = """
+ comment(Any_hashCode) = new DocComment("""
/** Returns a hash code value for the object.
*
*
@@ -195,36 +195,36 @@ abstract class SourcelessComments { *
* @return the hash code value for the object. *
*/ - """ + """) /*******************************************************************/ /* Documentation for AnyRef */ - comment(AnyRefClass) = """ + comment(AnyRefClass) = new DocComment(""" /**
* Class AnyRef
is the root class of all
* reference types.
*
o == arg0
is the same as if (o eq null) arg0 eq null else o.equals(arg0)
.
*
* @param arg0 the object to compare against this object for equality.
* @return true
if the receiver object is equivalent to the argument; false
otherwise.
*
o.ne(arg0)
is the same as !(o.eq(arg0))
.
*
* @param arg0 the object to compare against this object for reference dis-equality.
* @return false
if the argument is not a reference to the receiver object; true
otherwise.
*
@@ -232,9 +232,9 @@ abstract class SourcelessComments {
* invoked, as well as the interaction between finalize
* and non-local returns and exceptions, are all platform dependent.
*
@@ -242,9 +242,9 @@ abstract class SourcelessComments { * * @return a copy of the receiver object. *
*/ - """ + """) - comment(Object_getClass) = """ + comment(Object_getClass) = new DocComment(""" /** Returns a representation that corresponds to the dynamic class of the receiver object. * *@@ -252,17 +252,17 @@ abstract class SourcelessComments { * * @return a representation that corresponds to the dynamic class of the receiver object. *
*/ - """ + """) - comment(Object_notify) = """ + comment(Object_notify) = new DocComment(""" /** Wakes up a single thread that is waiting on the receiver object's monitor. */ - """ + """) - comment(Object_notifyAll) = """ + comment(Object_notifyAll) = new DocComment(""" /** Wakes up all threads that are waiting on the receiver object's monitor. */ - """ + """) - comment(Object_eq) = """ + comment(Object_eq) = new DocComment(""" /** This method is used to test whether the argument (arg0
) is a reference to the
* receiver object (this
).
*
@@ -304,11 +304,11 @@ abstract class SourcelessComments {
* @param arg0 the object to compare against this object for reference equality.
* @return true
if the argument is a reference to the receiver object; false
otherwise.
* */
- """
+ """)
/*******************************************************************/
- comment(AnyValClass) = """
+ comment(AnyValClass) = new DocComment("""
/**
* Class AnyVal
is the root class of all
* value types.
@@ -338,25 +338,25 @@ abstract class SourcelessComments {
* Double
are called
* floating point types.
*
* Class Boolean
has only two values: true
* and false
.
*
* Class Unit
has only one value: ()
.
*
* Class """ + sym.name + """
belongs to the value
* classes whose instances are not represented as objects by the
@@ -370,7 +370,7 @@ abstract class SourcelessComments {
* Values """ + maxValue + """
and """ + minValue + """
* are in defined in object scala.Math.
*
- * A template trait for iterable collections. + * A template trait for iterable collections of type `Iterable[A]`. *
*
* Collection classes mixing in this trait provide a method
@@ -36,11 +36,27 @@ import annotation.unchecked.uncheckedVariance
* Iterable
.
*
f
to all elements of this
- * iterable object.
- *
- * @param f A function that is applied for its side-effect to every element.
- * The result (of arbitrary type U) of function `f` is discarded.
- *
- * @note This method underlies the implementation of most other bulk operations.
- * Implementing `foreach` with `iterator` is often suboptimal.
- * So `foreach` should be overridden in concrete collection classes if a more
- * efficient implementation is available.
- */
- def foreach[U](f: A => U): Unit = iterator.foreach(f)
-
-
- /** Return true iff the given predicate `p` yields true for all elements
- * of this iterable.
- *
- * @note May not terminate for infinite-sized collections.
- * @param p the predicate
- */
- override def forall(p: A => Boolean): Boolean = iterator.forall(p)
-
- /** Return true iff there is an element in this iterable for which the
- * given predicate `p` yields true.
- *
- * @note May not terminate for infinite-sized collections.
- * @param p the predicate
- */
- override def exists(p: A => Boolean): Boolean = iterator.exists(p)
-
- /** Find and return the first element of the iterable object satisfying a
- * predicate, if any.
+ /** Applies a function `f` to all elements of this $coll.
*
- * @note may not terminate for infinite-sized collections.
- * @note Might return different results for different runs, unless this iterable is ordered.
- * @param p the predicate
- * @return an option containing the first element in the iterable object
- * satisfying p
, or None
if none exists.
- */
- override def find(p: A => Boolean): Option[A] = iterator.find(p)
-
- /** Does this iterable contain no elements?
- */
- override def isEmpty: Boolean = !this.iterator.hasNext
-
- /** Combines the elements of this iterable together using the binary
- * function f
, from right to left, and starting with
- * the value z
.
+ * Note: this method underlies the implementation of most other bulk operations.
+ * Subclasses should re-implement this method if a more efficient implementation exists.
*
- * @note Will not terminate for infinite-sized collections.
- * @note Might return different results for different runs, unless this iterable is ordered, or
- * the operator is associative and commutative.
- * @return f(a0, f(a1, f(..., f(an, z)...)))
- * if the iterable is [a0, a1, ..., an]
.
- */
- override def foldRight[B](z: B)(op: (A, B) => B): B =
- this.iterator.foldRight(z)(op)
-
- /** Combines the elements of this iterable object together using the binary
- * operator op
, from right to left
- * @note Will not terminate for infinite-sized collections.
- * @note Might return different results for different runs, unless this iterable is ordered, or
- * the operator is associative and commutative.
- * @param op The operator to apply
+ * @param f the function that is applied for its side-effect to every element.
+ * The result of function `f` is discarded.
*
- * @return a0 op (... op (an-1 op an)...)
- * if the iterable object has elements a0, a1, ...,
- * an
.
+ * @tparam U the type parameter describing the result of function `f`.
+ * This result will always be ignored. Typically `U` is `Unit`,
+ * but this is not necessary.
*
- * @throws Predef.UnsupportedOperationException if the iterator is empty.
- */
- override def reduceRight[B >: A](op: (A, B) => B): B =
- this.iterator.reduceRight(op)
-
- /** The iterable itself */
- override def toIterable: Iterable[A] = thisCollection
-
- /** The first element of this iterable.
+ * @usecase def foreach(f: A => Unit): Unit
*
- * @note Might return different results for different runs, unless this iterable is ordered
- * @throws Predef.NoSuchElementException if the iterable is empty.
+ * @param f the function that is applied for its side-effect to every element.
+ * The result of function `f` is discarded.
*/
- override def head: A =
- if (isEmpty)
- throw new NoSuchElementException
- else
- this.iterator.next
-
- /** Return an iterable consisting only of the first n
- * elements of this iterable, or else the whole iterable, if it has less
- * than n
elements.
- *
- * @param n the number of elements to take
- * @note Might return different results for different runs, unless this iterable is ordered
- */
- override def take(n: Int): Repr = {
+ def foreach[U](f: A => U): Unit =
+ iterator.foreach(f)
+
+ override /*TraversableLike*/ def forall(p: A => Boolean): Boolean =
+ iterator.forall(p)
+ override /*TraversableLike*/ def exists(p: A => Boolean): Boolean =
+ iterator.exists(p)
+ override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
+ iterator.find(p)
+/*
+ override /*TraversableLike*/ def mapFind[B](f: A => Option[B]): Option[B] =
+ iterator.mapFind(f)
+*/
+ override /*TraversableLike*/ def isEmpty: Boolean =
+ !iterator.hasNext
+ override /*TraversableLike*/ def foldRight[B](z: B)(op: (A, B) => B): B =
+ iterator.foldRight(z)(op)
+ override /*TraversableLike*/ def reduceRight[B >: A](op: (A, B) => B): B =
+ iterator.reduceRight(op)
+ override /*TraversableLike*/ def toIterable: Iterable[A] =
+ thisCollection
+
+ override /*TraversableLike*/ def head: A =
+ if (isEmpty) throw new NoSuchElementException
+ else iterator.next
+
+ override /*TraversableLike*/ def take(n: Int): Repr = {
val b = newBuilder
var i = 0
val it = iterator
@@ -164,17 +128,7 @@ self =>
b.result
}
- /** A sub-iterable starting at index `from`
- * and extending up to (but not including) index `until`.
- *
- * @note c.slice(from, to) is equivalent to (but possibly more efficient than)
- * c.drop(from).take(to - from)
- *
- * @param from The index of the first element of the returned subsequence
- * @param until The index of the element following the returned subsequence
- * @note Might return different results for different runs, unless this iterable is ordered
- */
- override def slice(from: Int, until: Int): Repr = {
+ override /*TraversableLike*/ def slice(from: Int, until: Int): Repr = {
val b = newBuilder
var i = from
val it = iterator drop from
@@ -185,13 +139,7 @@ self =>
b.result
}
- /** Returns the longest prefix of this iterable whose elements satisfy
- * the predicate p
.
- *
- * @param p the test predicate.
- * @note Might return different results for different runs, unless this iterable is ordered
- */
- override def takeWhile(p: A => Boolean): Repr = {
+ override /*TraversableLike*/ def takeWhile(p: A => Boolean): Repr = {
val b = newBuilder
val it = iterator
while (it.hasNext) {
@@ -202,10 +150,12 @@ self =>
b.result
}
- /** Returns the rightmost n
elements from this iterable.
+ /** Selects last ''n'' elements.
+ * $orderDependent
*
* @param n the number of elements to take
- * @note Might return different results for different runs, unless this iterable is ordered
+ * @return a $coll consisting only of the last `n` elements of this $coll, or else the
+ * whole $coll, if it has less than `n` elements.
*/
def takeRight(n: Int): Repr = {
val b = newBuilder
@@ -219,10 +169,12 @@ self =>
b.result
}
- /** Returns the iterable wihtout its rightmost n
elements.
+ /** Selects all elements except first ''n'' ones.
+ * $orderDependent
*
- * @param n the number of elements to take
- * @note Might return different results for different runs, unless this iterable is ordered
+ * @param n The number of elements to take
+ * @return a $coll consisting of all elements of this $coll except the first `n` ones, or else the
+ * empty $coll, if this $coll has less than `n` elements.
*/
def dropRight(n: Int): Repr = {
val b = newBuilder
@@ -235,17 +187,7 @@ self =>
b.result
}
- /** Fills the given array xs
with at most `len` elements of
- * this iterable starting at position `start`.
- * Copying will stop once either the end of the current iterable is reached or
- * `len` elements have been copied or the end of the array is reached.
- *
- * @note Will not terminate for infinite-sized collections.
- * @param xs the array to fill.
- * @param start starting index.
- * @param len number of elements to copy
- */
- override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
+ override /*TraversableLike*/ def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
var i = start
val end = (start + len) min xs.length
val it = iterator
@@ -255,10 +197,29 @@ self =>
}
}
- /** Returns an iterable formed from this iterable and another iterable
+ /** Returns a $coll formed from this $coll and another iterable collection
* by combining corresponding elements in pairs.
- * If one of the two iterables is longer than the other, its remaining elements are ignored.
+ * If one of the two collections is longer than the other, its remaining elements are ignored.
+ *
+ * $orderDependent
+ *
* @param that The iterable providing the second half of each result pair
+ * @tparam A1 the type of the first half of the returned pairs (this is always a supertype
+ * of the collection's element type `A`).
+ * @tparam B the type of the second half of the returned pairs
+ * @tparam That $zipthatinfo
+ * @param bf $zipbfinfo
+ * @return a new collection of type `That` containing pairs consisting of
+ * corresponding elements of this $coll and `that`. The length
+ * of the returned collection is the minimum of the lengths of this $coll$ and `that`.
+ *
+ * @usecase def zip[B](that: Iterable[B]): $Coll[(A, B)]
+ *
+ * @param that The iterable providing the second half of each result pair
+ * @tparam B the type of the second half of the returned pairs
+ * @return a new $coll containing pairs consisting of
+ * corresponding elements of this $coll and `that`. The length
+ * of the returned collection is the minimum of the lengths of this $coll$ and `that`.
*/
def zip[A1 >: A, B, That](that: Iterable[B])(implicit bf: CanBuildFrom[Repr, (A1, B), That]): That = {
val b = bf(repr)
@@ -269,25 +230,33 @@ self =>
b.result
}
- /** Returns an iterable formed from this iterable and the specified iterable
- * that
by associating each element of the former with
- * the element at the same position in the latter.
+ /** Returns a $coll formed from this $coll and another iterable collection
+ * by combining corresponding elements in pairs.
+ * If one of the two collections is shorter than the other,
+ * placeholder elements are used to extend the collection to the longer length.
*
- * @param that iterable that
may have a different length
- * as the self iterable.
- * @param thisElem element thisElem
is used to fill up the
- * resulting iterable if the self iterable is shorter than
- * that
- * @param thatElem element thatElem
is used to fill up the
- * resulting iterable if that
is shorter than
- * the self iterable
- * @return Sequence((a0,b0), ...,
- * (an,bn), (elem,bn+1),
- * ..., {elem,bm})
- * when [a0, ..., an] zip
- * [b0, ..., bm]
is
- * invoked where m > n
.
+ * $orderDependent
*
+ * @param that the iterable providing the second half of each result pair
+ * @param thisElem the element to be used to fill up the result if this $coll is shorter than `that`.
+ * @param thatElem the element to be used to fill up the result if `that` is shorter than this $coll.
+ * @return a new collection of type `That` containing pairs consisting of
+ * corresponding elements of this $coll and `that`. The length
+ * of the returned collection is the maximum of the lengths of this $coll$ and `that`.
+ * If this $coll is shorter than `that`, `thisElem` values are used to pad the result.
+ * If `that` is shorter than this $coll, `thatElem` values are used to pad the result.
+ *
+ * @usecase def zipAll[B](that: Iterable[B], thisElem: A, thatElem: B): $Coll[(A, B)]
+ *
+ * @param that The iterable providing the second half of each result pair
+ * @param thisElem the element to be used to fill up the result if this $coll is shorter than `that`.
+ * @param thatElem the element to be used to fill up the result if `that` is shorter than this $coll.
+ * @tparam B the type of the second half of the returned pairs
+ * @return a new $coll containing pairs consisting of
+ * corresponding elements of this $coll and `that`. The length
+ * of the returned collection is the maximum of the lengths of this $coll$ and `that`.
+ * If this $coll is shorter than `that`, `thisElem` values are used to pad the result.
+ * If `that` is shorter than this $coll, `thatElem` values are used to pad the result.
*/
def zipAll[B, A1 >: A, That](that: Iterable[B], thisElem: A1, thatElem: B)(implicit bf: CanBuildFrom[Repr, (A1, B), That]): That = {
val b = bf(repr)
@@ -302,7 +271,30 @@ self =>
b.result
}
- /** Zips this iterable with its indices (startiong from 0).
+ /** Zips this $coll with its indices.
+ *
+ * $orderDependent
+ *
+ * @tparam A1 the type of the first half of the returned pairs (this is always a supertype
+ * of the collection's element type `A`).
+ * @tparam That the class of the returned collection. Where possible, `That` is
+ * the same class as the current collection class `Repr`, but this
+ * depends on the element type `(A1, Int)` being admissible for that class,
+ * which means that an implicit instance of type `CanBuildFrom[Repr, (A1, Int), That]`.
+ * is found.
+ * @tparam bf an implicit value of class `CanBuildFrom` which determines the
+ * result class `That` from the current representation type `Repr`
+ * and the new element type `(A1, Int)`.
+ * @return A new collection of type `That` containing pairs consisting of all elements of this
+ * $coll paired with their index. Indices start at `0`.
+ *
+ * @usecase def zipWithIndex: $Coll[(A, Int)]
+ *
+ * @return A new $coll containing pairs consisting of all elements of this
+ * $coll paired with their index. Indices start at `0`.
+ * @example
+ * `List("a", "b", "c").zipWithIndex = List(("a", 0), ("b", 1), ("c", 2))`
+ *
*/
def zipWithIndex[A1 >: A, That](implicit bf: CanBuildFrom[Repr, (A1, Int), That]): That = {
val b = bf(repr)
@@ -314,12 +306,19 @@ self =>
b.result
}
- /** Checks if the other iterable object contains the same elements as this one.
+ /** Checks if the other iterable collection contains the same elements in the same order as this $coll.
+ *
+ * $orderDependent
+ * $willNotTerminateInf
+ *
+ * @param that the collection to compare with.
+ * @tparam B the type of the elements of collection `that`.
+ * @return `true`, if both collections contain the same elements in the same order, `false` otherwise.
*
- * @note will not terminate for infinite-sized iterables.
- * @param that the other iterable
- * @return true, iff both iterables contain the same elements in the same order.
- * @note Might return different results for different runs, unless this iterable is ordered
+ * @usecase def sameElements(that: Iterable[A]): Boolean
+ *
+ * @param that the collection to compare with.
+ * @return `true`, if both collections contain the same elements in the same order, `false` otherwise.
*/
def sameElements[B >: A](that: Iterable[B]): Boolean = {
val these = this.iterator
@@ -331,44 +330,36 @@ self =>
!these.hasNext && !those.hasNext
}
- /** Returns a stream with all elements in this iterable object.
- */
- override def toStream: Stream[A] = iterator.toStream
+ override /*TraversableLike*/ def toStream: Stream[A] = iterator.toStream
/** Method called from equality methods, so that user-defined subclasses can
* refuse to be equal to other collections of the same kind.
+ * @param that The object with which this $coll should be compared
+ * @return `true`, if this $coll can possibly equal `that`, `false` otherwise. The test
+ * takes into consideration only the run-time types of objects but ignores their elements.
*/
- override def canEqual(that: Any) = true
+ override /*TraversableLike*/ def canEqual(that: Any) = true
- /** Creates a view of this iterable @see IterableView
- */
- override def view = new IterableView[A, Repr] {
+ override /*TraversableLike*/ def view = new IterableView[A, Repr] {
protected lazy val underlying = self.repr
override def iterator = self.iterator
}
- /** A sub-iterable view starting at index `from`
- * and extending up to (but not including) index `until`.
- *
- * @param from The index of the first element of the slice
- * @param until The index of the element following the slice
- * @note The difference between `view` and `slice` is that `view` produces
- * a view of the current iterable, whereas `slice` produces a new iterable.
- *
- * @note Might return different results for different runs, unless this iterable is ordered
- * @note view(from, to) is equivalent to view.slice(from, to)
- */
- override def view(from: Int, until: Int) = view.slice(from, until)
+ override /*TraversableLike*/ def view(from: Int, until: Int) = view.slice(from, until)
+ /** @deprecated use `head' instead. */
@deprecated("use `head' instead") def first: A = head
- /** None
if iterable is empty. */
+ /** None
if iterable is empty.
+ * @deprecated "use `headOption' instead"
+ */
@deprecated("use `headOption' instead") def firstOption: Option[A] = headOption
/**
* returns a projection that can be used to call non-strict filter
,
* map
, and flatMap
methods that build projections
* of the collection.
+ * @deprecated "use `view' instead"
*/
@deprecated("use `view' instead")
def projection = view
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala
index fa5c2d3597..ac6cb890c4 100644
--- a/src/library/scala/collection/Iterator.scala
+++ b/src/library/scala/collection/Iterator.scala
@@ -636,6 +636,21 @@ trait Iterator[+A] { self =>
res
}
+ /** Applies option-valued function to successive elements of this iterator
+ * until a defined value is found.
+ *
+ * @param f the function to be applied to successive elements.
+ * @return an option value containing the first defined result of
+ * `f`, or `None` if `f` returns `None` for all all elements.
+ def mapFind[B](f: A => Option[B]): Option[B] = {
+ var res: Option[B] = None
+ while (res.isEmpty && hasNext) {
+ res = f(next())
+ }
+ res
+ }
+ */
+
/** Returns index of the first element satisfying a predicate, or -1.
*
* @note may not terminate for infinite-sized collections.
diff --git a/src/library/scala/collection/LinearSeqLike.scala b/src/library/scala/collection/LinearSeqLike.scala
index 4fb9b4ad79..08bb071da9 100644
--- a/src/library/scala/collection/LinearSeqLike.scala
+++ b/src/library/scala/collection/LinearSeqLike.scala
@@ -152,7 +152,17 @@ trait LinearSeqLike[+A, +Repr <: LinearSeqLike[A, Repr]] extends SeqLike[A, Repr
}
None
}
-
+/*
+ override def mapFind[B](f: A => Option[B]): Option[B] = {
+ var res: Option[B] = None
+ var these = this
+ while (res.isEmpty && !these.isEmpty) {
+ res = f(these.head)
+ these = these.tail
+ }
+ res
+ }
+*/
/** Combines the elements of this list together using the binary
* function f
, from left to right, and starting with
* the value z
.
diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala
index a1ea657553..a9ea82b2f9 100644
--- a/src/library/scala/collection/MapLike.scala
+++ b/src/library/scala/collection/MapLike.scala
@@ -14,28 +14,30 @@ import generic._
import mutable.{Builder, StringBuilder, MapBuilder}
import PartialFunction._
-/**
- * A generic template for maps from keys of type A
to values
- * of type B
.
- * To implement a concrete map, you need to provide implementations of the
- * following methods (where This
is the type of the map in
+/**
+ * A generic template for maps from keys of type `A` to values
+ * of type `B`.
+ *
+ * To implement a concrete map, 'you' need to provide implementations of the
+ * following methods (where `This` is the type of the map in
* question):
- *
- * def get(key: A): Option[B] - * def iterator: Iterator[(A, B)] - * def + [B1 >: B](kv: (A, B1)): This - * def -(key: A): This- *
+ * {{{
+ * def get(key: A): Option[B]
+ *
+ * def iterator: Iterator[(A, B)]
+ *
+ * def + [B1 >: B](kv: (A, B1)): This
+ *
+ * def -(key: A): This
+ * }}}
* If you wish that methods like
, take
, drop
,
* filter
return the same kind of map, you should also override:
- *
- * def empty: This- *
- * It is also good idea to override methods foreach
and
- * size
for efficiency.
- *
Seq[A]
represents sequences of elements
- * of type A
.
- * It adds the following methods to class Iterable:
- * `length`, `lengthCompare`, `apply`, `isDefinedAt`, `segmentLength`, `prefixLength`,
- * `indexWhere`, `indexOf`, `lastIndexWhere`, `lastIndexOf`, `reverse`, `reverseIterator`,
- * `startsWith`, `endsWith`, `indexOfSlice`, , `zip`, `zipAll`, `zipWithIndex`.
+/** A template trait for sequences of type `Seq[A]`, representing
+ * sequences of elements of type A
.
+ *
+ * Sequences are special cases of iterable collections of class `Iterable`.
+ * Unlike iterables, sequences always have a defined order of elements.
+ * Sequences provide a method `apply` for indexing. Indices range from `0` up the the `length` of
+ * a sequence. Sequences support a number to find occurrences of elements or subsequences, including
+ * `segmentLength`, `prefixLength`, `indexWhere`, `indexOf`, `lastIndexWhere`, `lastIndexOf`,
+ * `startsWith`, `endsWith`, `indexOfSlice`.
*
+ * Another way to see a sequence is as a `PartialFunction` from `Int` values
+ * to the element type of the sequence. The `isDefinedAt` method of a sequence
+ * returns `true` for the interval from `0` until `length`.
+ *
+ * Sequences can be accessed in reverse order of their elements, using methods
+ * `reverse` and `reverseIterator`.
+ *
+ * Sequences have two principle subtraits, `IndexedSeq` and `LinearSeq`, which give different guarantees for performance.
+ * An `IndexedSeq` provides fast random-access of elements and a fast `length` operation.
+ * A `LinearSeq` provides fast access only to the first element via `head`, but also
+ * has a fast `tail` operation.
*
* @author Martin Odersky
* @author Matthias Zenger
* @version 1.0, 16/07/2003
* @since 2.8
+ *
+ * @tparam A the element type of the collection
+ * @tparam Repr the type of the actual collection containing the elements.
+ *
+ * @define Coll Seq
+ * @define coll sequence
+ * @define thatinfo the class of the returned collection. Where possible, `That` is
+ * the same class as the current collection class `Repr`, but this
+ * depends on the element type `B` being admissible for that class,
+ * which means that an implicit instance of type `CanBuildFrom[Repr, B, That]`
+ * is found.
+ * @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`.
+ * @define orderDependent
+ * @define orderDependentFold
+ * @define mayNotTerminateInf
+ *
+ * Note: may not terminate for infinite-sized collections.
+ * @define willNotTerminateInf
+ *
+ * Note: will not terminate for infinite-sized collections.
*/
trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
override protected[this] def thisCollection: Seq[A] = this.asInstanceOf[Seq[A]]
override protected[this] def toCollection(repr: Repr): Seq[A] = repr.asInstanceOf[Seq[A]]
- /** Returns the length of the sequence.
+ /** The length of the $coll.
+ *
+ * $willNotTerminateInf
+ *
+ * Note: `xs.length` and `xs.size` yield the same result.
+ *
+ * @return the number of elements in this $coll.
*/
def length: Int
- /** Returns the elements at position `idx`
+ /** Selects an element by its index in the $coll
+ *
+ * @param idx The index to select
+ * @return the element of tyh
*/
def apply(idx: Int): A
- /** Result of comparing length
with operand len
.
- * returns x
where
- * x < 0
iff this.length < len
- * x == 0
iff this.length == len
- * x > 0
iff this.length > len
.
+ /** Compares the length of this $coll to a test value.
*
- * The method as implemented here does not call length directly; its running time
- * is O(length min len) instead of O(length). The method should be overwritten
- * if computing length is cheap.
+ * @param len the test value that gets compared with the length.
+ * @return A value `x` where
+ * {{{
+ * x < 0 if this.length < len
+ * x == 0 if this.length == len
+ * x > 0 if this.length > len
+ * }}}
+ * The method as implemented here does not call `length` directly; its running time
+ * is `O(length min len)` instead of `O(length)`. The method should be overwritten
+ * if computing `length` is cheap.
*/
def lengthCompare(len: Int): Int = {
var i = 0
@@ -142,18 +193,32 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
i - len
}
- /** Should always be length
*/
+ /** The size of this $coll, equivalent to `length`.
+ *
+ * $willNotTerminateInf
+ *
+ * @return the number of elements in this $coll.
+ */
override def size = length
- /** Is this partial function defined for the index x
?
+ /** Tests whether this $coll contains given index.
+ *
+ * The implementations of methods `apply` and `isDefinedAt` turn a `Seq[A]` into
+ * a `PartialFunction[Int, A]`.
+ *
+ * @param idx the index to test
+ * @return `true` if this $coll contains an element at position `idx`, `false` otherwise.
*/
- def isDefinedAt(x: Int): Boolean = (x >= 0) && (x < length)
+ def isDefinedAt(idx: Int): Boolean = (idx >= 0) && (idx < length)
- /** Returns length of longest segment starting from a start index `from`
- * such that every element of the segment satisfies predicate `p`.
- * @note may not terminate for infinite-sized collections.
- * @param p the predicate
- * @param from the start index
+ /** Computes length of longest segment whose elements all satisfy some preficate.
+ *
+ * $mayNotTerminateInf
+ *
+ * @param p the predicate used to test elements.
+ * @param from the index where the search starts.
+ * @return the length of the longest segment of this $coll starting from index `from`
+ * such that every element of the segment satisfies the predicate `p`.
*/
def segmentLength(p: A => Boolean, from: Int): Int = {
var i = 0
@@ -163,26 +228,34 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
i
}
- /** Returns length of longest prefix of this seqence
- * such that every element of the prefix satisfies predicate `p`.
- * @note may not terminate for infinite-sized collections.
- * @param p the predicate
+ /** Returns the length of the longest prefix whose elements all satisfy some preficate.
+ *
+ * $mayNotTerminateInf
+ *
+ * @param p the predicate used to test elements.
+ * @return the length of the longest prefix of this $coll
+ * such that every element of the segment satisfies the predicate `p`.
*/
def prefixLength(p: A => Boolean) = segmentLength(p, 0)
- /** Returns index of the first element satisfying a predicate, or -1, if none exists.
+ /** Finds index of first element satisfying some predicate.
*
- * @note may not terminate for infinite-sized collections.
- * @param p the predicate
+ * $mayNotTerminateInf
+ *
+ * @param p the predicate used to test elements.
+ * @return the index of the first element of this $coll that satisfies the predicate `p`,
+ * or `-1`, if none exists.
*/
def indexWhere(p: A => Boolean): Int = indexWhere(p, 0)
- /** Returns index of the first element starting from a start index
- * satisying a predicate, or -1, if none exists.
+ /** Finds index of the first element satisfying some predicate after or at some start index.
+ *
+ * $mayNotTerminateInf
*
- * @note may not terminate for infinite-sized collections.
- * @param p the predicate
- * @param from the start index
+ * @param p the predicate used to test elements.
+ * @param from the start index
+ * @return the index `>= from` of the first element of this $coll that satisfies the predicate `p`,
+ * or `-1`, if none exists.
*/
def indexWhere(p: A => Boolean, from: Int): Int = {
var i = from
@@ -192,63 +265,95 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
if (it.hasNext) i else -1
}
- /** Returns index of the first element satisying a predicate, or -1. */
- @deprecated("Use `indexWhere' instead")
+ /** Returns index of the first element satisying a predicate, or `-1`.
+ * @deprecated "Use `indexWhere` instead"
+ */
def findIndexOf(p: A => Boolean): Int = indexWhere(p)
- /** Returns the index of the first occurence of the specified
- * object in this sequence.
+ /** Finds index of first occurrence of some value in this $coll.
*
- * @note may not terminate for infinite-sized collections.
- * @param elem element to search for.
- * @return the index in this sequence of the first occurence of the
- * specified element, or -1 if the sequence does not contain
- * this element.
+ * $mayNotTerminateInf
+ *
+ * @param elem the element value to search for.
+ * @tparam B the type of the element `elem`.
+ * @return the index of the first element of this $coll that is equal (wrt `==`)
+ * tp `elem`, or `-1`, if none exists.
+ *
+ * @usecase def indexOf(elem: A): Int
+ *
+ * @param elem the element value to search for.
+ * @return the index of the first element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
*/
def indexOf[B >: A](elem: B): Int = indexOf(elem, 0)
- /** Returns the index of the first occurence of the specified
- * object in this sequence, starting from a start index, or
- * -1, if none exists.
+ /** Finds index of first occurrence of some value in this $coll after or at some start index.
+ *
+ * $mayNotTerminateInf
*
- * @note may not terminate for infinite-sized collections.
- * @param elem element to search for.
+ * @param elem the element value to search for.
+ * @tparam B the type of the element `elem`.
+ * @param from the start index
+ * @return the index `>= from` of the first element of this $coll that is equal (wrt `==`)
+ * tp `elem`, or `-1`, if none exists.
+ *
+ * @usecase def indexOf(elem: A): Int
+ *
+ * @param elem the element value to search for.
+ * @param from the start index
+ * @return the index `>= from` of the first element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
*/
def indexOf[B >: A](elem: B, from: Int): Int = indexWhere(elem ==, from)
- /** Returns the index of the last occurence of the specified element
- * in this sequence, or -1 if the sequence does not contain this element.
+ /** Finds index of last occurrence of some value in this $coll.
+ *
+ * $willNotTerminateInf
+ *
+ * @param elem the element value to search for.
+ * @tparam B the type of the element `elem`.
+ * @return the index of the last element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
*
- * @param elem element to search for.
- * @return the index in this sequence of the last occurence of the
- * specified element, or -1 if the sequence does not contain
- * this element.
+ * @usecase def lastIndexOf(elem: A): Int
+ *
+ * @param elem the element value to search for.
+ * @return the index of the last element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
*/
def lastIndexOf[B >: A](elem: B): Int = lastIndexWhere(elem ==)
- /** Returns the index of the last
- * occurence of the specified element in this sequence
- * before or at a given end index,
- * or -1 if the sequence does not contain this element.
- *
- * @param elem element to search for.
- * @param end the end index
- */
+ /** Finds index of last occurrence of some value in this $coll before or at a given end index.
+ *
+ * @param elem the element value to search for.
+ * @param end the end index.
+ * @tparam B the type of the element `elem`.
+ * @return the index `<= end` of the last element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
+ *
+ * @usecase def lastIndexOf(elem: A): Int
+ *
+ * @param elem the element value to search for.
+ * @return the index `<= end` of the last element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
+ */
def lastIndexOf[B >: A](elem: B, end: Int): Int = lastIndexWhere(elem ==, end)
- /** Returns index of the last element satisying a predicate, or -1, if none exists.
+ /** Finds index of last element satisfying some predicate.
+ *
+ * $willNotTerminateInf
*
- * @param p the predicate
- * @return the index of the last element satisfying p
,
- * or -1 if such an element does not exist
+ * @param p the predicate used to test elements.
+ * @return the index of the last element of this $coll that satisfies the predicate `p`,
+ * or `-1`, if none exists.
*/
def lastIndexWhere(p: A => Boolean): Int = lastIndexWhere(p, length - 1)
- /** Returns index of the last element not exceeding a given end index
- * and satisying a predicate, or -1 if none exists.
+ /** Finds index of last element satisfying some predicate before or at given end index.
*
- * @param end the end index
- * @param p the predicate
+ * @param p the predicate used to test elements.
+ * @return the index `<= end` of the last element of this $coll that satisfies the predicate `p`,
+ * or `-1`, if none exists.
*/
def lastIndexWhere(p: A => Boolean, end: Int): Int = {
var i = length - 1
@@ -257,8 +362,11 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
i
}
- /** A sequence of type C
consisting of all elements of
- * this sequence in reverse order.
+ /** Returns new $coll wih elements in reversed order.
+ *
+ * $willNotTerminateInf
+ *
+ * @return A new $coll with all elements of this $coll in reversed order.
*/
def reverse: Repr = {
var xs: List[A] = List()
@@ -270,18 +378,34 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
b.result
}
- /** Apply a function to all the elements of the sequence, and return the
- * reversed sequence of results. This is equivalent to a call to reverse
- * followed by a call to map
, but more efficient.
+ /**
+ * Builds a new collection by applying a function to all elements of this $coll and
+ * collecting the results in reversed order.
+ *
+ * $willNotTerminateInf
+ *
+ * Note: `xs.reverseMap(f)` is the same as `xs.reverse.map(f)` but might be more efficient.
+ *
+ * @param f the function to apply to each element.
+ * @tparam B the element type of the returned collection.
+ * @tparam That $thatinfo
+ * @param bf $bfinfo
+ * @return a new collection of type `That` resulting from applying the given function
+ * `f` to each element of this $coll and collecting the results in reversed order.
+ *
+ * @usecase def reverseMap[B](f: A => B): $Coll[B]
+ *
+ * Note: `xs.reverseMap(f)` is the same as `xs.reverse.map(f)` but might be more efficient.
*
- * @param f the function to apply to each elements.
- * @return the reversed seq of results.
+ * @param f the function to apply to each element.
+ * @tparam B the element type of the returned collection.
+ * @return a new $coll resulting from applying the given function
+ * `f` to each element of this $coll and collecting the results in reversed order.
*/
def reverseMap[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
var xs: List[A] = List()
for (x <- this)
xs = x :: xs
-
val b = bf(repr)
for (x <- xs)
b += f(x)
@@ -289,25 +413,30 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
b.result
}
- /** The elements of this sequence in reversed order
+ /** An iterator yielding elements in reversed order.
+ *
+ * $willNotTerminateInf
+ *
+ * Note: `xs.reverseIterator` is the same as `xs.reverse.iterator` but might be more efficient.
+ *
+ * @return an iterator yielding the elements of this $coll in reversed order
*/
def reverseIterator: Iterator[A] = toCollection(reverse).iterator
+ /** @deprecated use `reverseIterator` instead */
@deprecated("use `reverseIterator' instead")
def reversedElements = reverseIterator
- /**
- * Checks whether the argument sequence is contained at the
- * specified index within the receiver object.
+ /** Checks whether this $coll contains the given sequence at a given index.
*
* If the both the receiver object, this
and
* the argument, that
are infinite sequences
* this method may not terminate.
*
- * @return true if that
is contained in
- * this
, at the specified index, otherwise false
- *
- * @see String.startsWith
+ * @param that the candidate sequence
+ * @param offset the index where the sequence is searched.
+ * @return `true` if the sequence `that` is contained in this $coll at index `offset`,
+ * otherwise `false`.
*/
def startsWith[B](that: Seq[B], offset: Int): Boolean = {
val i = this.iterator drop offset
@@ -319,10 +448,10 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
!j.hasNext
}
- /**
- * Check whether the receiver object starts with the argument sequence.
+ /** Checks whether this $coll starts with the given sequence.
*
- * @return true if that
is a prefix of this
,
+ * @param that the candidate sequence
+ * @return `true` if this collection has `that` as a prefix, `false` otherwise.
* otherwise false
*/
def startsWith[B](that: Seq[B]): Boolean = startsWith(that, 0)
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index 44cb7ced63..0ff6227a3a 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -63,14 +63,12 @@ import immutable.{List, Stream, Nil, ::}
*
* @define Coll Traversable
* @define coll traversable collection
- * @define thatinfo
- * the class of the returned collection. Where possible, `That` is
+ * @define thatinfo the class of the returned collection. Where possible, `That` is
* the same class as the current collection class `Repr`, but this
* depends on the element type `B` being admissible for that class,
* which means that an implicit instance of type `CanBuildFrom[Repr, B, That]`
* is found.
- * @define bfinfo
- * an implicit value of class `CanBuildFrom` which determines the
+ * @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`.
* @define orderDependent
@@ -100,12 +98,13 @@ self =>
*/
def repr: Repr = this.asInstanceOf[Repr]
- /** The underlying collection seen as an instance of `Traversable`.
- * By default this is implemented as the `TraversableLike` object itself, but this can be overridden.
+ /** The underlying collection seen as an instance of `$Coll`.
+ * By default this is implemented as the current collection object itself,
+ * but this can be overridden.
*/
protected[this] def thisCollection: Traversable[A] = this.asInstanceOf[Traversable[A]]
- /** A conversion from collections of type `Repr` to `Traversable` objects.
+ /** A conversion from collections of type `Repr` to `$Coll` objects.
* By default this is implemented as just a cast, but this can be overridden.
*/
protected[this] def toCollection(repr: Repr): Traversable[A] = repr.asInstanceOf[Traversable[A]]
@@ -116,8 +115,9 @@ self =>
/** Applies a function `f` to all elements of this $coll.
*
- * Note: this method underlies the implementation of most other bulk operations.
- * It's important to implement this method in an efficient way.
+ * Note: this method underlies the implementation of most other bulk operations.
+ * It's important to implement this method in an efficient way.
+ *
*
* @param f the function that is applied for its side-effect to every element.
* The result of function `f` is discarded.
@@ -126,7 +126,7 @@ self =>
* This result will always be ignored. Typically `U` is `Unit`,
* but this is not necessary.
*
- * @usage def foreach(f: A => Unit): Unit
+ * @usecase def foreach(f: A => Unit): Unit
*
* @param f the function that is applied for its side-effect to every element.
* The result of function `f` is discarded.
@@ -184,7 +184,7 @@ self =>
* @return a new collection of type `That` which contains all elements of this $coll
* followed by all elements of `that`.
*
- * @usage def ++(that: Traversable[A]): $Coll[A]
+ * @usecase def ++(that: Traversable[A]): $Coll[A]
*
* @param that the traversable to append.
* @return a new $coll which contains all elements of this $coll
@@ -206,7 +206,7 @@ self =>
* @return a new collection of type `That` which contains all elements of this $coll
* followed by all elements of `that`.
*
- * @usage def ++(that: Iterator[A]): $Coll[A]
+ * @usecase def ++(that: Iterator[A]): $Coll[A]
*
* @param that the iterator to append.
* @return a new $coll which contains all elements of this $coll
@@ -228,7 +228,7 @@ self =>
* @return a new collection of type `That` resulting from applying the given function
* `f` to each element of this $coll and collecting the results.
*
- * @usage def map[B](f: A => B): $Coll[B]
+ * @usecase def map[B](f: A => B): $Coll[B]
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
@@ -251,7 +251,7 @@ self =>
* @return a new collection of type `That` resulting from applying the given collection-valued function
* `f` to each element of this $coll and concatenating the results.
*
- * @usage def flatMap[B](f: A => Traversable[B]): $Coll[B]
+ * @usecase def flatMap[B](f: A => Traversable[B]): $Coll[B]
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
@@ -266,7 +266,7 @@ self =>
/** Selects all elements of this $coll which satisfy a predicate.
*
- * @param p the predicate used used to test elements.
+ * @param p the predicate used to test elements.
* @return a new $coll consisting of all elements of this $coll that satisfy the given
* predicate `p`. The order of the elements is preserved.
*/
@@ -296,7 +296,7 @@ self =>
* `pf` to each element on which it is defined and collecting the results.
* The order of the elements is preserved.
*
- * @usage def partialMap[B](pf: PartialFunction[Any, B]): $Coll[B]
+ * @usecase def partialMap[B](pf: PartialFunction[Any, B]): $Coll[B]
*
* @param pf the partial function which filters and maps the $coll.
* @return a new $coll resulting from applying the given partial function
@@ -309,6 +309,34 @@ self =>
b.result
}
+ /** Builds a new collection by applying an option-valued function to all elements of this $coll
+ * on which the function is defined.
+ *
+ * @param f the option-valued function which filters and maps the $coll.
+ * @tparam B the element type of the returned collection.
+ * @tparam That $thatinfo
+ * @param bf $bfinfo
+ * @return a new collection of type `That` resulting from applying the option-valued function
+ * `f` to each element and collecting all defined results.
+ * The order of the elements is preserved.
+ *
+ * @usecase def filterMap[B](f: A => Option[B]): $Coll[B]
+ *
+ * @param pf the partial function which filters and maps the $coll.
+ * @return a new $coll resulting from applying the given option-valued function
+ * `f` to each element and collecting all defined results.
+ * The order of the elements is preserved.
+ def filterMap[B, That](f: A => Option[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
+ val b = bf(repr)
+ for (x <- this)
+ f(x) match {
+ case Some(y) => b += y
+ case _ =>
+ }
+ b.result
+ }
+ */
+
/** Partitions this $coll in two ${coll}s according to a predicate.
*
* @param p the predicate on which to partition.
@@ -356,7 +384,7 @@ self =>
*
* $mayNotTerminateInf
*
- * @param p the predicate used used to test elements.
+ * @param p the predicate used to test elements.
* @return `true` if the given predicate `p` holds for all elements
* of this $coll, otherwise `false`.
*/
@@ -373,7 +401,7 @@ self =>
*
* $mayNotTerminateInf
*
- * @param p the predicate used used to test elements.
+ * @param p the predicate used to test elements.
* @return `true` if the given predicate `p` holds for some of the elements
* of this $coll, otherwise `false`.
*/
@@ -388,7 +416,7 @@ self =>
/** Counts the number of elements in the $coll which satisfy a predicate.
*
- * @param p the predicate used used to test elements.
+ * @param p the predicate used to test elements.
* @return the number of elements satisfying the predicate `p`.
*
*
@@ -406,7 +434,7 @@ self =>
* $mayNotTerminateInf
* $orderDependent
*
- * @param p the predicate used used to test elements.
+ * @param p the predicate used to test elements.
* @return an option value containing the first element in the $coll
* that satisfies `p`, or `None` if none exists.
*/
@@ -419,6 +447,28 @@ self =>
result
}
+ /** Applies option-valued function to successive elements of this $coll
+ * until a defined value is found.
+ *
+ * $mayNotTerminateInf
+ * $orderDependent
+ *
+ * @param f the function to be applied to successive elements.
+ * @return an option value containing the first defined result of
+ * `f`, or `None` if `f` returns `None` for all all elements.
+ def mapFind[B](f: A => Option[B]): Option[B] = {
+ var result: Option[B] = None
+ breakable {
+ for (x <- this)
+ f(x) match {
+ case s @ Some(_) => result = s; break
+ case _ =>
+ }
+ }
+ result
+ }
+ */
+
/** Applies a binary operator to a start value and all elements of this $coll, going left to right.
*
* $willNotTerminateInf
@@ -430,9 +480,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going left to right with the start value `z` on the left:
* {{{
- * op(...op(z, x_1), x_2, ..., x_n)
+ * op(...op(z, x,,1,,), x,,2,,, ..., x,,n,,)
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
*
*/
def foldLeft[B](z: B)(op: (B, A) => B): B = {
@@ -454,9 +504,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going left to right with the start value `z` on the left:
* {{{
- * op(...op(op(z, x_1), x_2), ..., x_n)
+ * op(...op(op(z, x,,1,,), x,,2,,), ..., x,,n,,)
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
*/
def /: [B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
@@ -467,9 +517,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going right to left with the start value `z` on the right:
* {{{
- * op(x_1, op(x_2, ... op(x_n, z)...))
+ * op(x,,1,,, op(x,,2,,, ... op(x,,n,,, z)...))
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
*
* $willNotTerminateInf
* $orderDependentFold
@@ -492,9 +542,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going right to left with the start value `z` on the right:
* {{{
- * op(x_1, op(x_2, ... op(x_n, z)...))
+ * op(x,,1,,, op(x,,2,,, ... op(x,,n,,, z)...))
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
*/
def :\ [B](z: B)(op: (A, B) => B): B = foldRight(z)(op)
@@ -507,9 +557,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going left to right:
* {{{
- * op(...(op(x_1, x_2), ... ) , x_n)
+ * op(...(op(x,,1,,, x,,2,,), ... ) , x,,n,,)
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
* @throws `UnsupportedOperationException` if this $coll is empty.
*/
def reduceLeft[B >: A](op: (B, A) => B): B = {
@@ -544,9 +594,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going right to left:
* {{{
- * op(x_1, op(x_2, ..., op(x_(n-1), x_n)...))
+ * op(x,,1,,, op(x,,2,,, ..., op(x,,n-1,,, x,,n,,)...))
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
* @throws `UnsupportedOperationException` if this $coll is empty.
*/
def reduceRight[B >: A](op: (A, B) => B): B = {
@@ -576,9 +626,13 @@ self =>
* @tparam B the result type of the `+` operator.
* @return the sum of all elements of this $coll with respect to the `+` operator in `num`.
*
- * @usage sum: Num
- * @return the sum of all elements in this $coll of numbers of type `Num`.
- * `Num` must be a numeric type such as `Int`, `Double`, `BigDecimal`.
+ * @usecase def sum: Int
+ *
+ * @return the sum of all elements in this $coll of numbers of type `Int`.
+ * Instead of `Int`, any other type `T` with an implicit `Numeric[T]` implementation
+ * can be used as element type of the $coll and as result type of `sum`.
+ * Examples of such types are: `Long`, `Float`, `Double`, `BigInt`.
+ *
*/
def sum[B >: A](implicit num: Numeric[B]): B = {
var acc = num.zero
@@ -593,9 +647,12 @@ self =>
* @tparam B the result type of the `*` operator.
* @return the product of all elements of this $coll with respect to the `*` operator in `num`.
*
- * @usage product: Num
- * @return the product of all elements in this $coll of numbers of type `Num`.
- * `Num` must be a numeric type such as `Int`, `Double`, `BigDecimal`.
+ * @usecase def product: Int
+ *
+ * @return the product of all elements in this $coll of numbers of type `Int`.
+ * Instead of `Int`, any other type `T` with an implicit `Numeric[T]` implementation
+ * can be used as element type of the $coll and as result type of `product`.
+ * Examples of such types are: `Long`, `Float`, `Double`, `BigInt`.
*/
def product[B >: A](implicit num: Numeric[B]): B = {
var acc = num.one
@@ -609,7 +666,7 @@ self =>
* @tparam B The type over which the ordering is defined.
* @return the smallest element of this $coll with respect to the ordering `cmp`.
*
- * @usage min: A
+ * @usecase def min: A
* @return the smallest element of this $coll
*/
def min[B >: A](implicit cmp: Ordering[B]): A = {
@@ -626,7 +683,7 @@ self =>
* @tparam B The type over which the ordering is defined.
* @return the largest element of this $coll with respect to the ordering `cmp`.
*
- * @usage min: A
+ * @usecase def min: A
* @return the largest element of this $coll.
*/
def max[B >: A](implicit cmp: Ordering[B]): A = {
@@ -861,7 +918,7 @@ self =>
* @tparam B the type of the elements of the array.
*
*
- * @usage copyToArray(xs: Array[A], start: Int, len: Int): Unit
+ * @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Unit
*
* @param xs the array to fill.
* @param start the starting index.
@@ -891,7 +948,7 @@ self =>
* @param start the starting index.
* @tparam B the type of the elements of the array.
*
- * @usage def copyToArray(xs: Array[A], start: Int): Unit
+ * @usecase def copyToArray(xs: Array[A], start: Int): Unit
*
* @param xs the array to fill.
* @param start the starting index.
@@ -907,7 +964,7 @@ self =>
* be available.
* @return an array containing all elements of this $coll.
*
- * @usage toArray: Array[A]
+ * @usecase def toArray: Array[A]
* @return an array containing all elements of this $coll.
* A `ClassManifest` must be available for the element type of this $coll.
*/
@@ -1054,7 +1111,6 @@ self =>
/** Creates a non-strict view of this $coll.
*
* @return a non-strict view of this $coll.
- * @see TraversableView
*/
def view = new TraversableView[A, Repr] {
protected lazy val underlying = self.repr
@@ -1107,7 +1163,7 @@ self =>
* `f` to each element of the outer $coll that satisfies predicate `p`
* and collecting the results.
*
- * @usage def map[B](f: A => B): $Coll[B]
+ * @usecase def map[B](f: A => B): $Coll[B]
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
@@ -1132,7 +1188,7 @@ self =>
* @return a new collection of type `That` resulting from applying the given collection-valued function
* `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.
*
- * @usage def flatMap[B](f: A => Traversable[B]): $Coll[B]
+ * @usecase def flatMap[B](f: A => Traversable[B]): $Coll[B]
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
@@ -1156,7 +1212,7 @@ self =>
* This result will always be ignored. Typically `U` is `Unit`,
* but this is not necessary.
*
- * @usage def foreach(f: A => Unit): Unit
+ * @usecase def foreach(f: A => Unit): Unit
*
* @param f the function that is applied for its side-effect to every element.
* The result of function `f` is discarded.
diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala
index d03858a68f..92f1b5bba6 100644
--- a/src/library/scala/collection/mutable/MapLike.scala
+++ b/src/library/scala/collection/mutable/MapLike.scala
@@ -103,6 +103,15 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
*/
override def updated[B1 >: B](key: A, value: B1): mutable.Map[A, B1] = this + ((key, value))
+ /** If given key is already in this map, returns associated value
+ * Otherwise, computes value from given expression `op`, stores with key
+ * in map and returns that value.
+ */
+ def cached(key: A, op: => B) = get(key) match {
+ case Some(v) => v
+ case None => val v = op; update(key, v); v
+ }
+
/** Add a new key/value mapping and return the map itself.
*
* @param kv the key/value mapping to be added
--
cgit v1.2.3