diff options
author | Martin Odersky <odersky@gmail.com> | 2009-05-08 16:33:15 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-05-08 16:33:15 +0000 |
commit | 14a631a5fec42d04d0723355a0b93e482b5e4662 (patch) | |
tree | f639c2a22e89e193b9abea391993ecfd4d5326ee /src/library | |
parent | 2379eb4ebbd28c8892b50a1d9fa8a687099eea4d (diff) | |
download | scala-14a631a5fec42d04d0723355a0b93e482b5e4662.tar.gz scala-14a631a5fec42d04d0723355a0b93e482b5e4662.tar.bz2 scala-14a631a5fec42d04d0723355a0b93e482b5e4662.zip |
massive new collections checkin.
Diffstat (limited to 'src/library')
342 files changed, 8419 insertions, 21053 deletions
diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index 45d12b433e..282885f0bb 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -11,8 +11,8 @@ package scala - -import Predef._ +import scala.collection.generic._ +import scala.collection.mutable.{Vector, ArrayBuffer} import compat.Platform.arraycopy /** This object contains utility methods operating on arrays. @@ -20,9 +20,15 @@ import compat.Platform.arraycopy * @author Martin Odersky * @version 1.0 */ -object Array { +object Array extends SequenceFactory[Array] { + import runtime.BoxedArray; import scala.runtime.ScalaRunTime.boxArray; + + type Coll = Array[_] + implicit def builderFactory[A]: BuilderFactory[A, Array[A], Coll] = new BuilderFactory[A, Array[A], Coll] { def apply(from: Coll) = newBuilder[A] } + def newBuilder[A]: Builder[A, Array[A], Any] = new ArrayBuffer[A].mapResult(_.toArray) + private def slowcopy( src : AnyRef, srcPos : Int, @@ -76,46 +82,20 @@ object Array { result } - /** Create a an array containing of successive integers. - * - * @param from the value of the first element of the array - * @param end the value of the last element fo the array plus 1 - * @return the sorted array of all integers in range [from;end). - */ - def range(start: Int, end: Int): Array[Int] = { - val result = new Array[Int](end - start) - for (i <- start until end) result(i - start) = i - result - } + /** Returns array of length 0 */ + override def empty[A]: Array[A] = new Array[A](0) - /** Create an array with given elements. + /** Create an array with given elements. * * @param xs the elements to put in the array * @return the array containing elements xs. */ - def apply[A <: AnyRef](xs: A*): Array[A] = { - val array = new Array[A](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } - - -/* The following metod clashes with the previous one, and has therefore been - * removed. Note that this is a choice between efficiency and generality. - * The previous factory method is more efficient than the one that has been - * commented out. Since it is anyway possible to create a polymorphic array - * using - * new Array[T] - * it was preferred to restrict the definition of the factory method. - - def Array[A](xs: A*): Array[A] = { + override def apply[A](xs: A*): Array[A] = { val array = new Array[A](xs.length) var i = 0 for (x <- xs.elements) { array(i) = x; i += 1 } array } -*/ def apply(xs: Boolean*): Array[Boolean] = { val array = new Array[Boolean](xs.length) @@ -180,13 +160,34 @@ object Array { array } + /** Create array with given dimensions */ + def ofDim[A](n1: Int): Array[A] = + new Array[A](n1) + def ofDim[A](n1: Int, n2: Int): Array[Array[A]] = + tabulate(n1)(_ => ofDim[A](n2)) + def ofDim[A](n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = + tabulate(n1)(_ => ofDim[A](n2, n3)) + def ofDim[A](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = + tabulate(n1)(_ => ofDim[A](n2, n3, n4)) + def ofDim[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = + tabulate(n1)(_ => ofDim[A](n2, n3, n4, n5)) + + /** Create array with given dimensions + * @deprecated use ofDim instead */ + @deprecated def withDims[A](n1: Int): Array[A] = ofDim(n1) + @deprecated def withDims[A](n1: Int, n2: Int): Array[Array[A]] = ofDim(n1, n2) + @deprecated def withDims[A](n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = ofDim(n1, n2, n3) + @deprecated def withDims[A](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = ofDim(n1, n2, n3, n4) + @deprecated def withDims[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = ofDim(n1, n2, n3, n4, n5) + /** Create an array containing several copies of an element. * * @param n the length of the resulting array * @param elem the element composing the resulting array * @return an array composed of n elements all equal to elem + * @deprecated use `Array.fill` instead. */ - def make[A](n: Int, elem: A): Array[A] = { + @deprecated def make[A](n: Int, elem: A): Array[A] = { val a = new Array[A](n) var i = 0 while (i < n) { @@ -198,8 +199,9 @@ object Array { /** Create an array containing the values of a given function <code>f</code> * over given range <code>[0..n)</code> + * @deprecated use `Array.tabulate` instead. */ - def fromFunction[A](f: Int => A)(n: Int): Array[A] = { + @deprecated def fromFunction[A](f: Int => A)(n: Int): Array[A] = { val a = new Array[A](n) var i = 0 while (i < n) { @@ -211,95 +213,31 @@ object Array { /** Create an array containing the values of a given function <code>f</code> * over given range <code>[0..n1, 0..n2)</code> + * @deprecated use `Array.tabulate` instead. */ - def fromFunction[A](f: (Int, Int) => A)(n1: Int, n2: Int): Array[Array[A]] = + @deprecated def fromFunction[A](f: (Int, Int) => A)(n1: Int, n2: Int): Array[Array[A]] = fromFunction(i => fromFunction(f(i, _))(n2))(n1) /** Create an array containing the values of a given function <code>f</code> * over given range <code>[0..n1, 0..n2, 0..n3)</code> + * @deprecated use `Array.tabulate` instead. */ - def fromFunction[A](f: (Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = + @deprecated def fromFunction[A](f: (Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = fromFunction(i => fromFunction(f(i, _, _))(n2, n3))(n1) /** Create an array containing the values of a given function <code>f</code> * over given range <code>[0..n1, 0..n2, 0..n3, 0..n4)</code> + * @deprecated use `Array.tabulate` instead. */ - def fromFunction[A](f: (Int, Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = + @deprecated def fromFunction[A](f: (Int, Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = fromFunction(i => fromFunction(f(i, _, _, _))(n2, n3, n4))(n1) /** Create an array containing the values of a given function <code>f</code> * over given range <code>[0..n1, 0..n2, 0..n3, 0..n4, 0..n5)</code> + * @deprecated use `Array.tabulate` instead. */ - def fromFunction[A](f: (Int, Int, Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = + @deprecated def fromFunction[A](f: (Int, Int, Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = fromFunction(i => fromFunction(f(i, _, _, _, _))(n2, n3, n4, n5))(n1) - - /** Create array with given dimensions */ - def withDims[A](n1: Int): Array[A] = - new Array[A](n1) - def withDims[A](n1: Int, n2: Int): Array[Array[A]] = - fromFunction(_ => withDims[A](n2))(n1) - def withDims[A](n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = - fromFunction(_ => withDims[A](n2, n3))(n1) - def withDims[A](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = - fromFunction(_ => withDims[A](n2, n3, n4))(n1) - def withDims[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = - fromFunction(_ => withDims[A](n2, n3, n4, n5))(n1) - - /** This method is called as a result of a pattern match { case Array(...) => } or val Array(...) = .... - * - * @param x the selector value - * @return array wrapped in an option - */ - def unapplySeq[A](x: Array[A]): Option[Seq[A]] = Some(x) - - trait ArrayLike[A] extends RandomAccessSeq.Mutable[A] { - def force : Array[A] - } - - trait Projection[A] extends RandomAccessSeq.MutableProjection[A] with ArrayLike[A] { - protected def newArray[B >: A](length : Int, elements : Iterator[A]) : Array[B] - override def toArray[B >: A] = (newArray(length, elements))//:Any).asInstanceOf[Array[B]] - override def force : Array[A] = toArray - override def drop( from: Int) = slice(from, length) - override def take(until: Int) = slice(0, until) - override def dropWhile(p: A => Boolean) = { - val c = length + 1 - drop((findIndexOf(!p(_)) + c) % c) - } - override def takeWhile(p: A => Boolean) = { - val c = length + 1 - take((findIndexOf(!p(_)) + c) % c) - } - override def slice(from0: Int, until0: Int): Projection[A] = new RandomAccessSeq.MutableSlice[A] with Projection[A] { - override def from = from0 - override def until = until0 - override def underlying = Projection.this - override protected def newArray[B >: A](length: Int, elements: Iterator[A]) = - underlying.newArray(length, elements) - override def slice(from0: Int, until0: Int) = - Projection.this.slice(from + from0, from + until0) - } - - - override def reverse : Projection[A] = new Projection[A] { - override protected def newArray[B >: A](length : Int, elements : Iterator[A]) = - Projection.this.newArray(length, elements) - def update(idx : Int, what : A) : Unit = Projection.this.update(length - idx - 1, what) - def length = Projection.this.length - def apply(idx : Int) = Projection.this.apply(length - idx - 1) - override def stringPrefix = Projection.this.stringPrefix + "R" - } - } - trait Array0[A] extends RandomAccessSeq.Mutable[A] with ArrayLike[A] { - override def projection : Projection[A] = throw new Error - override def slice(from : Int, until : Int) : Projection[A] = projection.slice(from, until) - override def take(until : Int) : Projection[A] = projection.take(until) - override def drop(from : Int) : Projection[A] = projection.drop(from) - override def dropWhile(p: A => Boolean) = projection.dropWhile(p) - override def takeWhile(p: A => Boolean) = projection.takeWhile(p) - override def reverse = projection.reverse - override def force = asInstanceOf[Array[A]] - } } /** This class represents polymorphic arrays. <code>Array[T]</code> is Scala's representation @@ -308,52 +246,63 @@ object Array { * @author Martin Odersky * @version 1.0 */ -final class Array[A](_length: Int) extends Array.Array0[A] { +final class Array[A](_length: Int) extends Vector[A] with VectorTemplate[A, Array[A]] { + + override protected[this] def newBuilder: Builder[A, Array[A], Any] = throw new Error() - /** Multidimensional array creation */ - def this(dim1: Int, dim2: Int) = { + /** Multidimensional array creation + * @deprecated use Array.ofDim instead + */ + @deprecated def this(dim1: Int, dim2: Int) = { this(dim1) throw new Error() } - /** Multidimensional array creation */ - def this(dim1: Int, dim2: Int, dim3: Int) = { + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int) = { this(dim1) throw new Error() } - /** Multidimensional array creation */ - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int) = { + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int) = { this(dim1) throw new Error() } - /** Multidimensional array creation */ - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int) = { + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int) = { this(dim1); throw new Error() } - /** Multidimensional array creation */ - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int) = { + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int) = { this(dim1) throw new Error() } - /** Multidimensional array creation */ - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int) = { + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int) = { this(dim1) throw new Error() } - /** Multidimensional array creation */ - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int) = { + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int) = { this(dim1) throw new Error() } - /** Multidimensional array creation */ - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int, dim9: Int) = { + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int, dim9: Int) = { this(dim1) throw new Error() } @@ -396,66 +345,6 @@ final class Array[A](_length: Int) extends Array.Array0[A] { */ override def update(i: Int, x: A) { throw new Error() } - /** An iterator returning the elements of this array, starting from 0. - */ - override def elements: Iterator[A] = throw new Error() - - /** @deprecated use <code>slice(from,end).force</code> instead */ - def subArray(from: Int, end: Int): Array[A] = throw new Error() - - /** Returns an array consisting of all elements of this array that satisfy the - * predicate <code>p</code>. The order of the elements is preserved. - * - * @param p the predicate used to filter the array. - * @return the elements of this array satisfying <code>p</code>. - */ - override def filter(p: A => Boolean): Array[A] = throw new Error() - - /** Returns an array consisting of all elements of this array followed - * by all elements of the argument iterable. - */ - override def ++[B >: A](that: Iterable[B]): Array[B] = throw new Error() - - /** Returns the array resulting from applying the given function <code>f</code> to each - * element of this array. - * - * @param f function to apply to each element. - * @return <code>[f(a0), ..., f(an)]</code> if this array is <code>[a0, ..., an]</code>. - */ - override def map[B](f: A => B): Array[B] = throw new Error() - - /** Applies the given function <code>f</code> to each element of - * this array, then concatenates the results. - * - * @param f the function to apply on each element. - * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if - * this array is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>. - */ - override def flatMap[B](f: A => Iterable[B]): Array[B] = throw new Error() - - /** Returns an array formed from this array and the specified array - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * If one of the two arrays is longer than the other, its remaining elements are ignored. - * - * @return <code>Array({a<sub>0</sub>,b<sub>0</sub>}, ..., - * {a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>})</code> when - * <code>Array(a<sub>0</sub>, ..., a<sub>m</sub>) - * zip Array(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked. - */ - def zip[B](that: Array[B]): Array[(A, B)] = throw new Error() - - /** Returns an array that pairs each element of this array - * with its index, counting from 0. - * - * @return the array <code>Array({a<sub>0</sub>,0}, {a<sub>1</sub>,1},...)</code> - * where <code>a<sub>i</sub></code> are the elements of this stream. - */ - def zipWithIndex: Array[(A, Int)] = throw new Error() - - /** Returns an array that contains all indices of this array */ - def indices: Array[Int] = throw new Error() - /** * @return a deep string representation of this array. */ @@ -510,4 +399,6 @@ final class Array[A](_length: Int) extends Array.Array0[A] { */ def deepEquals(that: Any): Boolean = throw new Error() + /** @deprecated use slice instead */ + @deprecated def subArray(from: Int, end: Int): Array[A] = throw new Error() } diff --git a/src/library/scala/BufferedIterator.scala b/src/library/scala/BufferedIterator.scala deleted file mode 100644 index 86f5f23967..0000000000 --- a/src/library/scala/BufferedIterator.scala +++ /dev/null @@ -1,194 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - - -import Predef._ - -/** Buffered iterators are iterators which allow to inspect the next - * element without discarding it. - * - * @author Martin Odersky - * @author SeanMcDirmid - * @version 2.0, 16/04/2007 - */ -trait BufferedIterator[+A] extends Iterator[A] { - /** Checks what the next available element is. - * - * @return the current element - */ - def head : A - def headOpt = if (!hasNext) None else Some(head) - override def buffered: this.type = this - /** iterates over and applies <code>f</code> to the next element - * if this iterator has a next element that <code>f</code> is defined for. - */ - def readIf[T](f : PartialFunction[A,T]) : Option[T] = - if (hasNext && f.isDefinedAt(head)) - Some(f(next)) - else None - - /** iterates over elements as long as <code>f</code> is true - * for each element, returns whether anything was read - */ - def readWhile(f : A => Boolean) : Boolean = { - var read = false - while (hasNext && f(head)) { - next - read = true - } - read - } - def advanced : BufferedIterator.Advanced[A] = new BufferedIterator.Default[A] { - protected def fill(sz : Int) : Seq[A] = if (BufferedIterator.this.hasNext) (BufferedIterator.this.next) :: Nil else Nil - } -} - -object BufferedIterator { - import collection.mutable.{Buffer, ListBuffer} - - trait Advanced[+A] extends BufferedIterator[A] { - /** returns the first <code>sz</code> elements that will be iterated by this iterator, - * or fewer if the iterator has less elements left to iterate over - */ - def peekList(sz : Int) : Seq[A] - - /** Checks what the next available element is. - * - * @return the current element - */ - def head: A = peek(0) - - /** return the <code>n</code>th element that will be iterated by this iterator */ - def peek(n : Int) : A = { - val lst = peekList(n + 1); - if (n == 0) { - return if (lst.isEmpty) defaultPeek - else lst(0) - } - - val i = lst.elements - var m = 0 - while (m < n && i.hasNext) { - i.next; m += 1 - } - if (!i.hasNext) defaultPeek - else i.next - } - /** element returned when no element left to iterate over; - * throws <code>NoSuchElementException</code> by default - */ - protected def defaultPeek : A = throw new Predef.NoSuchElementException - - /** true if elements of <code>seq</code> will be iterated over next in this iterator - */ - def startsWith(seq : Seq[Any]) : Boolean = { - var sz = seq.length - val j = peekList(sz).elements - val i = seq.elements - while (i.hasNext && j.hasNext) - if (i.next != j.next) return false - return !i.hasNext - } - def readIfStartsWith(seq : Seq[Any]) : Boolean = { - if (startsWith(seq)) { - var i = 0 - while (i < seq.length) { - next; i = i + 1 - } - true - } else false - } - override def counted : CountedIterator[A] with Advanced[A] = new CountedIterator[A] with Advanced[A] { - private var cnt = -1 - def count = cnt - override def hasNext: Boolean = Advanced.this.hasNext - override def next: A = { cnt += 1; Advanced.this.next } - override def peekList(sz : Int) : Seq[A] = Advanced.this.peekList(sz) - override protected def defaultPeek : A = Advanced.this.defaultPeek - override def counted : this.type = this - } - override def hasNext = !peekList(1).isEmpty - override def toString = { - val list = peekList(0) - if (!list.isEmpty) "peek " + list else "***" - } - - override def advanced : this.type = this - } - - trait PutBack[+A] extends Advanced[A] { - protected[this] def putBack(a : A) : Unit - override def counted : CountedIterator[A] with PutBack[A] = new CountedIterator[A] with PutBack[A] { - private var cnt = -1 - def count = cnt - override protected def defaultPeek : A = PutBack.this.defaultPeek - override def next: A = { cnt += 1; PutBack.this.next } - override def hasNext: Boolean = PutBack.this.hasNext - override def peekList(sz : Int) : Seq[A] = PutBack.this.peekList(sz) - override protected[this] def putBack(a : A) : Unit = { - if (cnt <= 0) throw new IllegalArgumentException - PutBack.this.putBack(a) - cnt = cnt - 1 - } - override def counted : this.type = this - } - protected[this] def flushFrom[B <% Seq[A]](i : Default[B]) = - i.forget.reverse.foreach(_.reverse.foreach(putBack)) - } - - - abstract class Default[+A] extends PutBack[A] { - import scala.collection.mutable.ListBuffer - private[this] val lookahead = new ListBuffer[A] // = Nil - override protected[this] def putBack(a : A) : Unit = a +: lookahead - override protected def defaultPeek : A = throw new Predef.NoSuchElementException - override def hasNext = !lookahead.isEmpty || super.hasNext - - /** used to fill lookahead buffer. <code>sz</code> can be used by implementations as a heauristic to determine how many elements are desired */ - protected def fill(sz : Int) : Seq[A] - - private[BufferedIterator] def forget : List[A] = { - val ret = lookahead.toList - lookahead.clear - ret - } - - override def peekList(sz : Int) : Seq[A] = { - if (sz == 0) return lookahead.readOnly - else if (sz == 1) { - if (!lookahead.isEmpty) return lookahead.readOnly - fill(sz) match { - case Seq.singleton(x) => lookahead += x - case next => lookahead ++= next - } - return lookahead.readOnly - } - var sz0 = lookahead.length - while (sz0 < sz) { - val next = fill(sz - sz0) - if (next.isEmpty) return lookahead.readOnly - sz0 += next.length - lookahead ++= next - } - lookahead.readOnly - } - override def next : A = { - val lst = peekList(1) - if (lst.isEmpty) throw new Predef.NoSuchElementException - lookahead.remove(0) - lst(0) - } - } -} - - diff --git a/src/library/scala/Collection.scala b/src/library/scala/Collection.scala deleted file mode 100644 index 21c8dc060a..0000000000 --- a/src/library/scala/Collection.scala +++ /dev/null @@ -1,47 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - - -import Predef._ - -/** Variant of <code>Iterable</code> used to describe - * collections with a finite number of elements. - * Basically, this trait just adds size and toString to Iterable, - * as most of the methods in Iterable already assume finite-ness. - * - * @author Sean McDirmid - */ -trait Collection[+A] extends Iterable[A] { - /** Returns the number of elements in this collection. - * - * @return number of collection elements. - */ - def size : Int - /** Converts this iterable to a fresh Array with elements. - */ - def toArray[B >: A]: Array[B] = toList.toArray - - override def toString = mkString(stringPrefix + "(", ", ", ")") - - /** Defines the prefix of this object's <code>toString</code> representation. - */ - protected def stringPrefix : String = { - var string = this.getClass.getName - val idx1 = string.lastIndexOf('.' : Int) - if (idx1 != -1) string = string.substring(idx1 + 1) - val idx2 = string.indexOf('$') - if (idx2 != -1) string = string.substring(0, idx2) - string - } -} - diff --git a/src/library/scala/CollectionProxy.scala b/src/library/scala/CollectionProxy.scala deleted file mode 100644 index fae285d3dd..0000000000 --- a/src/library/scala/CollectionProxy.scala +++ /dev/null @@ -1,55 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - -import scala.collection.mutable.Buffer - - -/** This class implements a proxy for iterable objects. It forwards - * all calls to a different iterable object. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.0, 31/12/2006 - */ -trait CollectionProxy[+A] extends Collection[A] with IterableProxy[A] { - - def self: Collection[A] - override def size = self.size - override def toArray[B >: A] : Array[B] = self.toArray -/* - override def elements: Iterator[A] = self.elements - override def map[B](f: A => B): Collection[B] = self map f - override def flatMap[B](f: A => Collection[B]): Collection[B] = self flatMap f - override def filter(p: A => Boolean): Collection[A] = self filter p - override def takeWhile(p: A => Boolean): Collection[A] = self takeWhile p - override def dropWhile(p: A => Boolean): Collection[A] = self dropWhile p - override def drop(n: Int): Collection[A] = self drop n - override def foreach(f: A => Unit): Unit = self foreach f - override def forall(p: A => Boolean): Boolean = self forall p - override def exists(p: A => Boolean): Boolean = self exists p - override def find(p: A => Boolean): Option[A] = self find p - override def findIndexOf(p: A => Boolean): Int = self findIndexOf p - override def indexOf[B >: A](elem: B): Int = self indexOf elem - override def foldLeft[B](z: B)(op: (B, A) => B): B = (self foldLeft z)(op) - override def foldRight[B](z: B)(op: (A, B) => B): B = (self foldRight z)(op) - override def /:[B](z: B)(op: (B, A) => B): B = (z /: self)(op) - override def :\[B](z: B)(op: (A, B) => B): B = (self :\ z)(op) - override def reduceLeft[B >: A](op: (B, B) => B): B = self reduceLeft op - override def reduceRight[B >: A](op: (B, B) => B): B = self reduceRight op - override def sameElements[B >: A](that: Iterable[B]): Boolean = self sameElements that - override def copyToBuffer[B >: A](dest: Buffer[B]): Unit = self copyToBuffer dest - override def toList: List[A] = self.toList - override def mkString(start: String, sep: String, end: String): String = self.mkString(start, sep, end) - override def addString(buf: StringBuilder, start: String, sep: String, end: String): StringBuilder = self.addString(buf, start, sep, end) - */ -} diff --git a/src/library/scala/CountedIterator.scala b/src/library/scala/CountedIterator.scala index 0734e1111f..490743d733 100644 --- a/src/library/scala/CountedIterator.scala +++ b/src/library/scala/CountedIterator.scala @@ -12,20 +12,12 @@ package scala /** Counted iterators keep track of the number of elements seen so far - * - * @author Martin Odersky - * @version 1.0, 16/07/2003 + * @deprecated use iterator.zipWithIndex instead */ -trait CountedIterator[+A] extends Iterator[A] { +@deprecated trait CountedIterator[+A] extends Iterator[A] { /** counts the elements in this iterator; counts start at 0 */ def count: Int override def counted : this.type = this - override def buffered: BufferedIterator[A] with CountedIterator[A] = new BufferedIterator.Default[A] with CountedIterator[A] { - protected def fill(sz : Int) = if (CountedIterator.this.hasNext) (CountedIterator.this.next) :: Nil else Nil - override def count = CountedIterator.this.count - peekList(0).length - override def counted : this.type = this - override def buffered : this.type = this - } } diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala index 577d58ca53..6a9e1331b1 100644 --- a/src/library/scala/Enumeration.scala +++ b/src/library/scala/Enumeration.scala @@ -13,6 +13,8 @@ package scala import scala.collection.mutable.{Map, HashMap} +import scala.collection.immutable.{Set, BitSet} +import scala.collection.generic.{Builder, BuilderFactory, AddingBuilder, SetTemplate} /** <p> * Defines a finite set of values specific to the enumeration. Typically @@ -59,8 +61,9 @@ abstract class Enumeration(initial: Int, names: String*) { def this() = this(0, null) def this(names: String*) = this(0, names: _*) - /** The name of this enumeration. */ - protected def name = { + /** The name of this enumeration. + */ + override def toString = { val cname = this.getClass().getName() if (cname endsWith "$") cname.substring(0, cname.length() - 1) @@ -72,10 +75,21 @@ abstract class Enumeration(initial: Int, names: String*) { /** The mapping from the integer used to identifying values to the actual * values. */ - private val values: Map[Int, Value] = new HashMap + private val vmap: Map[Int, Value] = new HashMap /** The cache listing all values of this enumeration. */ - lazy private val vcache: List[Value] = values.values.toList.sort(_.id < _.id) + @transient private var vset: ValueSet = null + @transient private var vsetDefined = false + + /** The values of this enumeration as a set. + */ + def values: ValueSet = { + if (!vsetDefined) { + vset = new ValueSet(BitSet.empty ++ (vmap.values map (_.id))) + vsetDefined = true + } + vset + } /** The integer to use to identify the next created value. */ protected var nextId = initial @@ -89,15 +103,11 @@ abstract class Enumeration(initial: Int, names: String*) { /** The highest integer amongst those used to identify values in this * enumeration. */ - protected final def maxId = topId - - /** The value in this enumeration identified by integer <code>x</code>. */ - final def apply(x: Int): Value = values(x) - - /** A new iterator over all values of this enumeration. */ - final def elements: Iterator[Value] = vcache.elements + final def maxId = topId - override def toString(): String = vcache.mkString("{", ", ", "}") + /** The value of this enumeration with given id `x` + */ + final def withId(x: Int): Value = vmap(x) /** Returns a Value from this Enumeration whose name matches * the argument <var>s</var>. @@ -108,7 +118,7 @@ abstract class Enumeration(initial: Int, names: String*) { * @return <tt>Some(Value)</tt> if an enumeration's name matches <var>s</var>, * else <tt>None</tt> */ - def valueOf(s: String) = elements find (_.toString == s) + def withName(s: String): Value = values.find(_.toString == s).get /** Creates a fresh value, part of this enumeration. */ protected final def Value: Value = Value(nextId) @@ -152,17 +162,20 @@ abstract class Enumeration(initial: Int, names: String*) { case _ => false } override def hashCode: Int = id.hashCode + /** this enumeration value as an <code>Int</code> bit mask. * @throws IllegalArgumentException if <code>id</code> is greater than 31 + * @deprecated */ - def mask32: Int = { + @deprecated def mask32: Int = { if (id >= 32) throw new IllegalArgumentException 1 << id } /** this enumeration value as an <code>Long</code> bit mask. * @throws IllegalArgumentException if <code>id</code> is greater than 63 + * @deprecated */ - def mask64: Long = { + @deprecated def mask64: Long = { if (id >= 64) throw new IllegalArgumentException 1L << id } @@ -181,19 +194,49 @@ abstract class Enumeration(initial: Int, names: String*) { def this(name: String) = this(nextId, name) def this() = this(nextId, if (nextName.hasNext) nextName.next else nextId.toString()) - assert(!values.isDefinedAt(i)) - values(i) = this + assert(!vmap.isDefinedAt(i)) + vmap(i) = this + vsetDefined = false nextId = i + 1 if (nextId > topId) topId = nextId def id = i override def toString() = - if (name eq null) Enumeration.this.name + "(" + i + ")" + if (name eq null) Enumeration.this + "(" + i + ")" else name private def readResolve(): AnyRef = - if (values ne null) values(i) + if (vmap ne null) vmap(i) else this } + /** A class for sets of values + * Iterating through this set will yield values in increasing order of their ids. + * @param ids The set of ids of values, organized as a BitSet. + */ + class ValueSet private[Enumeration] (val ids: BitSet) extends Set[Value] with SetTemplate[Value, ValueSet] { + override def empty = ValueSet.empty + def contains(v: Value) = ids contains (v.id) + def + (value: Value) = new ValueSet(ids + value.id) + def - (value: Value) = new ValueSet(ids - value.id) + def elements = ids.elements map withId + override def stringPrefix = Enumeration.this + ".ValueSet" + } + + /** A factory object for value sets */ + object ValueSet { + /** The empty value set */ + val empty = new ValueSet(BitSet.empty) + /** A value set consisting of given elements */ + def apply(elems: Value*): ValueSet = { + var s = empty + for (elem <- elems) s = s + elem // !!! change to s += elem --> error + s + } + /** A builder object for value sets */ + def newBuilder: Builder[Value, ValueSet, Any] = new AddingBuilder(empty) + /** The implicit builder for value sets */ + implicit def builderFactory: BuilderFactory[Value, ValueSet, ValueSet] = new BuilderFactory[Value, ValueSet, ValueSet] { def apply(from: ValueSet) = newBuilder } + } + /** A set that efficiently stores enumeration values as bits. * * @author Sean McDirmid @@ -218,8 +261,9 @@ abstract class Enumeration(initial: Int, names: String*) { * <b>if</b> (e.flags.contains(flags.Private)) * e.flags0 = (e.flags | flags.Final).underlying; * </pre> + * @deprecated use ValueSet instead */ - protected abstract class SetXX extends collection.immutable.Set[Value] { + @deprecated abstract class SetXX extends collection.immutable.Set[Value] { /** either Int or Long */ type Underlying <: AnyVal @@ -255,7 +299,7 @@ abstract class Enumeration(initial: Int, names: String*) { def +(value: Value): TSet = this | value def ++(set: TSet): TSet = this | set def **(set: TSet): TSet = this & set - def size = { + override def size = { var x = underlyingAsLong var sz = 0 while (x != 0) { @@ -276,23 +320,23 @@ abstract class Enumeration(initial: Int, names: String*) { def next = { if (underlying == 0) throw new NoSuchElementException while ((underlying & 1) == 0) shift - val ret = values(bit) + val ret = vmap(bit) shift ret } } - def empty[B]: scala.collection.immutable.Set[B] = new scala.collection.immutable.HashSet[B]; } /** An enumeration bit set that can handle enumeration values with ids up * to 31 in an <code>Int</code>. + * @deprecated use ValueSet instead */ - protected class Set32(val underlying: Int) extends SetXX { + @deprecated class Set32(val underlying: Int) extends SetXX { def this() = this(0) type Underlying = Int type TSet = Set32 def underlyingAsLong = { - if (underlying >= 0) underlying.toLong + if (underlying >= 0) underlying.toLong else { val underlying0 = (~(1 << 31)) & underlying assert(underlying0 >= 0) @@ -314,8 +358,9 @@ abstract class Enumeration(initial: Int, names: String*) { /** An enumeration bit set that can handle enumeration values with ids up * to 63 in a <code>Long</code>. + * @deprecated use ValueSet instead */ - protected class Set64(val underlying: Long) extends SetXX { + @deprecated class Set64(val underlying: Long) extends SetXX { def this() = this(0) type Underlying = Long type TSet = Set64 @@ -345,4 +390,58 @@ abstract class Enumeration(initial: Int, names: String*) { assert(m == 1) bit } + + /** The name of this enumeration. + * @deprecated use toString instead + */ + @deprecated def name = toString + + /** The value in this enumeration identified by integer <code>x</code>. + * @deprecated use withId instead. + */ + @deprecated final def apply(x: Int): Value = withId(x) + + /** @deprecated use withName instead + */ + @deprecated def valueOf(s: String) = values.find(_.toString == s) + + /** A new iterator over all values of this enumeration. + * @deprecated use values.elements instead + */ + @deprecated final def elements: Iterator[Value] = values.elements + + /** Apply a function f to all values of this enumeration. + * @deprecated use values.foreach instead + */ + @deprecated def foreach(f: Value => Unit): Unit = elements foreach f + + /** Apply a predicate p to all values of this enumeration and return + * true, iff the predicate yields true for all values. + * @deprecated use values.forall instead + */ + @deprecated def forall(p: Value => Boolean): Boolean = elements forall p + + /** Apply a predicate p to all values of this enumeration and return + * true, iff there is at least one value for which p yields true. + * @deprecated use values.exists instead + */ + @deprecated def exists(p: Value => Boolean): Boolean = elements exists p + + /** Returns an iterator resulting from applying the given function f to each + * value of this enumeration. + * @deprecated use values.map instead + */ + @deprecated def map[B](f: Value => B): Iterator[B] = elements map f + + /** Applies the given function f to each value of this enumeration, then + * concatenates the results. + * @deprecated use values.flatMap instead + */ + @deprecated def flatMap[B](f: Value => Iterator[B]): Iterator[B] = elements flatMap f + + /** Returns all values of this enumeration that satisfy the predicate p. + * The order of values is preserved. + * @deprecated use values.filter instead + */ + @deprecated def filter(p: Value => Boolean): Iterator[Value] = elements filter p } diff --git a/src/library/scalax/Fractional.scala b/src/library/scala/Fractional.scala index b29a903519..81366a80b9 100755 --- a/src/library/scalax/Fractional.scala +++ b/src/library/scala/Fractional.scala @@ -1,4 +1,4 @@ -package scalax +package scala trait Fractional[T] extends Numeric[T] { def div(x: T, y: T): T diff --git a/src/library/scalax/collection/mutable/DefaultEntry.scala b/src/library/scala/Immutable.scala index 2fb0f62226..5e9fff003a 100644..100755 --- a/src/library/scalax/collection/mutable/DefaultEntry.scala +++ b/src/library/scala/Immutable.scala @@ -5,12 +5,8 @@ ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ +package scala -// $Id: DefaultEntry.scala 16893 2009-01-13 13:09:22Z cunei $ - - -package scalax.collection.mutable - -@serializable -final class DefaultEntry[A, B](val key: A, var value: B) - extends HashEntry[A, DefaultEntry[A, B]] +/** A marker trait for all immutable datastructures such as imutable collections + */ +trait Immutable diff --git a/src/library/scalax/Integral.scala b/src/library/scala/Integral.scala index 2e80b1bb7b..bfd4bf9f48 100755 --- a/src/library/scalax/Integral.scala +++ b/src/library/scala/Integral.scala @@ -1,4 +1,4 @@ -package scalax +package scala trait Integral[T] extends Numeric[T] { def quot(x: T, y: T): T diff --git a/src/library/scala/Iterable.scala b/src/library/scala/Iterable.scala deleted file mode 100644 index a09d23863a..0000000000 --- a/src/library/scala/Iterable.scala +++ /dev/null @@ -1,512 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - - -import Predef._ -import collection.mutable.{Buffer,ArrayBuffer} - -/** Various utilities for instances of <a href="Iterable.html">Iterable</a>. - * - * @author Matthias Zenger - * @version 1.1, 04/02/2004 - */ -object Iterable { -/* - implicit def view[A <% Ordered[A]](x: Iterable[A]): Ordered[Iterable[A]] = - new Ordered[Iterable[A]] { - def compare[B >: Iterable[A] <% Ordered[B]](that: B): Int = that match { - case y: Iterable[A] => - val xs = x.elements - val ys = y.elements - var res = 0 - while (xs.hasNext && ys.hasNext && (res == 0)) { - res = xs.next compare ys.next - } - if (xs.hasNext) 1 - else if (ys.hasNext) -1 - else res - case _ => - -(that compare x) - } - } -*/ - /** The minimum element of a non-empty sequence of ordered elements */ - def min[A <% Ordered[A]](seq: Iterable[A]): A = { - val xs = seq.elements - if (!xs.hasNext) throw new IllegalArgumentException("min(<empty>)") - var min = xs.next - while (xs.hasNext) { - val x = xs.next - if (x < min) min = x - } - min - } - - /** The maximum element of a non-empty sequence of ordered elements */ - def max[A <% Ordered[A]](seq: Iterable[A]): A = { - val xs = seq.elements - if (!xs.hasNext) throw new IllegalArgumentException("max(<empty>)") - var max = xs.next - while (xs.hasNext) { - val x = xs.next - if (max < x) max = x - } - max - } - - /** The empty iterable object */ - val empty = new Iterable[Nothing] { - def elements = Iterator.empty - } - /** A non-strict projection of an iterable. - * @author Sean McDirmid - */ - trait Projection[+A] extends Iterable[A] { - override def projection = this - /** convert to a copied strict collection */ - def force : Iterable[A] = toList - - /** non-strict */ - override def filter(p : A => Boolean) : Projection[A] = new Projection[A] { - def elements = Projection.this.elements.filter(p) - } - /** non-strict */ - override def map[B](f: A => B) : Projection[B] = new Projection[B] { - def elements = Projection.this.elements.map(f) - } - /** non-strict */ - override def flatMap[B](f: A => Iterable[B]) : Projection[B] = new Projection[B] { - def elements = Projection.this.elements.flatMap(a => f(a).elements) - } - /** non-strict */ - override def takeWhile(p: A => Boolean): Projection[A] = new Projection[A] { - def elements = Projection.this.elements.takeWhile(p) - } - /** The projection resulting from the concatenation of this projection with the <code>rest</code> projection. - * @param rest The projection that gets appended to this projection - */ - def append[B >: A](rest : => Iterable[B]): Projection[B] = new Projection[B] { - def elements = Projection.this.elements ++ rest.elements - } - } -} - - -/** Collection classes mixing in this class provide a method - * <code>elements</code> which returns an iterator over all the - * elements contained in the collection. - * - * @note If a collection has a known <code>size</code>, it should also sub-type <code>Collection</code>. - * Only potentially unbounded collections should directly sub-class <code>Iterable</code>. - * @author Matthias Zenger - * @version 1.1, 04/02/2004 - */ -trait Iterable[+A] { - - /** Creates a new iterator over all elements contained in this - * object. - * - * @return the new iterator - */ - def elements: Iterator[A] - - /** Appends two iterable objects. - * - * @return the new iterable object - * @deprecated use <code>++</code> instead - * @note Will not terminate for infinite-sized collections. - */ - @deprecated - def concat[B >: A](that: Iterable[B]): Collection[B] = - this ++ that - - /** Appends two iterable objects. - * - * @return the new iterable object - * @note Will not terminate for infinite-sized collections. - */ - def ++ [B >: A](that: Iterable[B]): Collection[B] = { - val buf = new ArrayBuffer[B] - this copyToBuffer buf - that copyToBuffer buf - buf - } - - /** Returns the iterable resulting from applying the given function - * <code>f</code> to each element of this iterable. - * - * @note Will not terminate for infinite-sized collections. - * @param f function to apply to each element. - * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> - * if this iterable is <code>a<sub>0</sub>, ..., an</code>. - */ - def map[B](f: A => B): Iterable[B] = { - val buf = new ArrayBuffer[B] - val elems = elements - while (elems.hasNext) buf += f(elems.next) - buf - } - - /** Applies the given function <code>f</code> to each element of - * this iterable, then concatenates the results. - * - * @note Will not terminate for infinite-sized collections. - * @param f the function to apply on each element. - * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if - * this iterable is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. - */ - def flatMap[B](f: A => Iterable[B]): Iterable[B] = { - val buf = new ArrayBuffer[B] - val elems = elements - while (elems.hasNext) f(elems.next) copyToBuffer buf - buf - } - - /** Returns all the elements of this iterable that satisfy the - * predicate <code>p</code>. The order of the elements is preserved. - * - * @note Will not terminate for infinite-sized collections. - * @param p the predicate used to filter the list. - * @return the elements of this list satisfying <code>p</code>. - */ - def filter(p: A => Boolean): Iterable[A] = { - val buf = new ArrayBuffer[A] - val elems = elements - while (elems.hasNext) { val x = elems.next; if (p(x)) buf += x } - buf - } - - /** Partitions this iterable in two iterables according to a predicate. - * - * @param p the predicate on which to partition - * @return a pair of iterables: the iterable that satisfy the predicate - * <code>p</code> and the iterable that do not. - * The relative order of the elements in the resulting iterables - * is the same as in the original iterable. - */ - def partition(p: A => Boolean): (Iterable[A], Iterable[A]) = { - val matched = new ArrayBuffer[A] - val failed = new ArrayBuffer[A] - val elems = elements - while (elems.hasNext) { val x = elems.next; if (p(x)) matched += x else failed += x } - (matched, failed) - } - - /** Returns the longest prefix of this iterable whose elements satisfy - * the predicate <code>p</code>. - * - * @note May not terminate for infinite-sized collections. - * @param p the test predicate. - * @return the longest prefix of this iterable whose elements satisfy - * the predicate <code>p</code>. - */ - def takeWhile(p: A => Boolean): Iterable[A] = - (new ArrayBuffer[A] ++ elements.takeWhile(p)) - - /** Returns the longest suffix of this iterable whose first element - * does not satisfy the predicate <code>p</code>. - * - * @note May not terminate for infinite-sized collections. - * @param p the test predicate. - * @return the longest suffix of the iterable whose first element - * does not satisfy the predicate <code>p</code>. - */ - def dropWhile(p: A => Boolean): Collection[A] = - (new ArrayBuffer[A] ++ elements.dropWhile(p)) - - /** Returns an iterable consisting only over the first <code>n</code> - * elements of this iterable, or else the whole iterable, if it has less - * than <code>n</code> elements. - * - * @deprecated API does not make sense for non-ordered collections - * @param n the number of elements to take - * @return the new iterable - */ - @deprecated def take(n: Int): Collection[A] = - (new ArrayBuffer[A] ++ elements.take(n)) - - /** Returns this iterable without its <code>n</code> first elements - * If this iterable has less than <code>n</code> elements, the empty - * iterable is returned. - * - * @note Will not terminate for infinite-sized collections. - * @deprecated API does not make sense for non-ordered collections - * @param n the number of elements to drop - * @return the new iterable - */ - @deprecated def drop(n: Int): Collection[A] = - (new ArrayBuffer[A] ++ elements.drop(n)) - - /** Apply a function <code>f</code> to all elements of this - * iterable object. - * - * @note Will not terminate for infinite-sized collections. - * @param f a function that is applied to every element. - */ - def foreach(f: A => Unit): Unit = elements.foreach(f) - - /** Apply a predicate <code>p</code> to all elements of this - * iterable object and return true, iff the predicate yields - * true for all elements. - * - * @note May not terminate for infinite-sized collections. - * @param p the predicate - * @return true, iff the predicate yields true for all elements. - */ - def forall(p: A => Boolean): Boolean = elements.forall(p) - - /** Apply a predicate <code>p</code> to all elements of this - * iterable object and return true, iff there is at least one - * element for which <code>p</code> yields true. - * - * @note May not terminate for infinite-sized collections. - * @param p the predicate - * @return true, iff the predicate yields true for at least one element. - */ - def exists(p: A => Boolean): Boolean = elements.exists(p) - - /** Find and return the first element of the iterable object satisfying a - * predicate, if any. - * - * @note may not terminate for infinite-sized collections. - * @param p the predicate - * @return the first element in the iterable object satisfying <code>p</code>, - * or <code>None</code> if none exists. - */ - def find(p: A => Boolean): Option[A] = elements.find(p) - - /** Returns index of the first element satisying a predicate, or -1. - * - * @note may not terminate for infinite-sized collections. - * @param p the predicate - * @return the index of the first element satisfying <code>p</code>, - * or -1 if such an element does not exist - * @deprecated Method is pushed to <code>Seq</code>, will be removed from <code>Iterable</code>. - */ - @deprecated def findIndexOf(p: A => Boolean): Int = - elements.findIndexOf(p) - - /** Returns the index of the first occurence of the specified - * object in this iterable object. - * - * @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. - * @deprecated Method is pushed to <code>Seq</code>, will be removed from <code>Iterable</code>. - */ - @deprecated def indexOf[B >: A](elem: B): Int = - elements.indexOf(elem) - - /** Combines the elements of this iterable object together using the binary - * function <code>f</code>, from left to right, and starting with - * the value <code>z</code>. - * - * @note Will not terminate for infinite-sized collections. - * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...), - * a<sub>n</sub>)</code> if the list is - * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>. - */ - def foldLeft[B](z: B)(op: (B, A) => B): B = elements.foldLeft(z)(op) - - /** Combines the elements of this list together using the binary - * function <code>f</code>, from right to left, and starting with - * the value <code>z</code>. - * - * @note Will not terminate for infinite-sized collections. - * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code> - * if the list is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>. - */ - def foldRight[B](z: B)(op: (A, B) => B): B = elements.foldRight(z)(op) - - /** Similar to <code>foldLeft</code> but can be used as - * an operator with the order of list and zero arguments reversed. - * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code> - * @note Will not terminate for infinite-sized collections. - */ - def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op) - - /** An alias for <code>foldRight</code>. - * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code> - * @note Will not terminate for infinite-sized collections. - */ - def :\[B](z: B)(op: (A, B) => B): B = foldRight(z)(op) - - /** Combines the elements of this iterable object together using the binary - * operator <code>op</code>, from left to right - * @note Will not terminate for infinite-sized collections. - * @param op The operator to apply - * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code> - if the iterable object has elements - * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>. - * @throws Predef.UnsupportedOperationException if the iterable object is empty. - */ - def reduceLeft[B >: A](op: (B, A) => B): B = elements.reduceLeft(op) - -/** Combines the elements of this iterable object together using the binary - * operator <code>op</code>, from right to left - * @note Will not terminate for infinite-sized collections. - * @param op The operator to apply - * - * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code> - * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., - * a<sub>n</sub></code>. - * - * @throws Predef.UnsupportedOperationException if the iterator is empty. - */ - def reduceRight[B >: A](op: (A, B) => B): B = elements.reduceRight(op) - - /** Copy all elements to a given buffer - * @note Will not terminate for infinite-sized collections. - * @param dest The buffer to which elements are copied - * @note Will not terminate if not finite. - */ - def copyToBuffer[B >: A](dest: Buffer[B]): Unit = elements copyToBuffer dest - - /** Checks if the other iterable object contains the same elements. - * - * @note will not terminate for infinite-sized collections. - * @param that the other iterable object - * @return true, iff both iterable objects contain the same elements in the same order. - */ - def sameElements[B >: A](that: Iterable[B]): Boolean = { - val ita = this.elements - val itb = that.elements - var res = true - while (res && ita.hasNext && itb.hasNext) { - res = (ita.next == itb.next) - } - !ita.hasNext && !itb.hasNext && res - } - - /** - * Returns a list containing all of the elements in this iterable object. - * @note Will not terminate for infinite-sized collections. - */ - def toList: List[A] = elements.toList - - /** - * Returns a sequence containing all of the elements in this iterable object. - * @note Will not terminate for infinite-sized collections. - */ - def toSeq: Seq[A] = toList - - /** - * Returns a stream containing all of the elements in this iterable object. - * @note consider using <code>projection</code> for lazy behavior. - */ - def toStream: Stream[A] = Stream.fromIterator(elements) - - /** Returns a string representation of this iterable object. The resulting string - * begins with the string <code>start</code> and is finished by the string - * <code>end</code>. Inside, the string representations of elements (w.r.t. - * the method <code>toString()</code>) are separated by the string - * <code>sep</code>. - * - * @ex <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code> - * @note Will not terminate for infinite-sized collections. - * @param start starting string. - * @param sep separator string. - * @param end ending string. - * @return a string representation of this iterable object. - */ - def mkString(start: String, sep: String, end: String): String = { - val buf = new StringBuilder() - addString(buf, start, sep, end).toString - } - - /** Returns a string representation of this iterable object. The string - * representations of elements (w.r.t. the method <code>toString()</code>) - * are separated by the string <code>sep</code>. - * - * @note Will not terminate for infinite-sized collections. - * @param sep separator string. - * @return a string representation of this iterable object. - */ - def mkString(sep: String): String = this.mkString("", sep, "") - - /** Converts a collection into a flat <code>String</code> by each element's toString method. - * @note Will not terminate for infinite-sized collections. - */ - def mkString: String = mkString("") - - /** Write all elements of this string into given string builder. - * - * @note Will not terminate for infinite-sized collections. - * @param buf the StringBuilder to which elements are appended - * @param start starting string. - * @param sep separator string. - * @param end ending string. - * @return the <code>buf</code> StringBuilder object - */ - def addString(buf: StringBuilder, start: String, sep: String, end: String): StringBuilder = { - buf.append(start) - val elems = elements - if (elems.hasNext) buf.append(elems.next) - while (elems.hasNext) { - buf.append(sep); buf.append(elems.next) - } - buf.append(end) - } - - /** Write all elements of this string into given string builder. - * - * @note Will not terminate for infinite-sized collections. - * @param buf the StringBuilder to which elements are appended - * @param sep separator string. - * @return the <code>buf</code> StringBuilder object - */ - def addString(buf: StringBuilder, sep: String): StringBuilder = addString(buf, "", sep, "") - - /** Write all elements of this string into given string builder, with no separator string - * between elements. - * @note Will not terminate for infinite-sized collections. - * @param buf the StringBuilder to which elements are appended - * @return the <code>buf</code> StringBuilder object - */ - def addString(buf: StringBuilder): StringBuilder = addString(buf, "", "", "") - - - /** Fills the given array <code>xs</code> with the elements of - * this sequence starting at position <code>start</code>. - * - * @note Will not terminate for infinite-sized collections. - * @param xs the array to fill. - * @param start starting index. - * @pre the array must be large enough to hold all elements. - */ - def copyToArray[B >: A](xs: Array[B], start: Int): Unit = - elements.copyToArray(xs, start) - - - /** Is this collection empty? */ - def isEmpty = !elements.hasNext - - /** - * returns a projection that can be used to call non-strict <code>filter</code>, - * <code>map</code>, and <code>flatMap</code> methods that build projections - * of the collection. - */ - def projection : Iterable.Projection[A] = new Iterable.Projection[A] { - def elements = Iterable.this.elements - override def force = Iterable.this - } - - /** returns true iff this collection has a bound size. - * Many APIs in this trait will not work on collections of - * unbound sizes. - */ - def hasDefiniteSize = true - -} diff --git a/src/library/scala/IterableProxy.scala b/src/library/scala/IterableProxy.scala deleted file mode 100644 index 99a83d72a8..0000000000 --- a/src/library/scala/IterableProxy.scala +++ /dev/null @@ -1,79 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - -import scala.collection.mutable.Buffer - - -/** This class implements a proxy for iterable objects. It forwards - * all calls to a different iterable object. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.0, 31/12/2006 - */ -trait IterableProxy[+A] extends Iterable[A] with Proxy { - - override def self: Iterable[A] - - override def elements = self.elements - @deprecated - override def concat [B >: A](that: Iterable[B]) = self concat that - override def ++[B >: A](that: Iterable[B]) = self ++ that - override def map[B](f: A => B) = self map f - override def flatMap[B](f: A => Iterable[B]) = self flatMap f - override def filter(p: A => Boolean) = self filter p - override def partition(p: A => Boolean) = self partition p - override def takeWhile(p: A => Boolean) = self takeWhile p - override def dropWhile(p: A => Boolean) = self dropWhile p - @deprecated override def take(n: Int) = self take n - @deprecated override def drop(n: Int) = self drop n - override def foreach(f: A => Unit) = self foreach f - override def forall(p: A => Boolean) = self forall p - override def exists(p: A => Boolean) = self exists p - override def find(p: A => Boolean) = self find p - @deprecated override def findIndexOf(p: A => Boolean) = self findIndexOf p - @deprecated override def indexOf[B >: A](elem: B): Int = self indexOf elem - override def foldLeft[B](z: B)(op: (B, A) => B) = (self foldLeft z)(op) - override def foldRight[B](z: B)(op: (A, B) => B) = (self foldRight z)(op) - override def /:[B](z: B)(op: (B, A) => B) = (z /: self)(op) - override def :\[B](z: B)(op: (A, B) => B) = (self :\ z)(op) - override def reduceLeft[B >: A](op: (B, A) => B) = self reduceLeft op - override def reduceRight[B >: A](op: (A, B) => B) = self reduceRight op - override def copyToBuffer[B >: A](dest: Buffer[B]) = self copyToBuffer dest - override def sameElements[B >: A](that: Iterable[B]) = self sameElements that - - override def toList = self.toList - override def toSeq = self.toSeq - override def toStream = self.toStream - - override def mkString(start: String, sep: String, end: String) = self.mkString(start, sep, end) - override def mkString(sep: String) = self.mkString(sep) - override def mkString = self.mkString - - override def addString(buf: StringBuilder, start: String, sep: String, end: String) = - self.addString(buf, start, sep, end) - - override def addString(buf: StringBuilder, sep: String) = - self.addString(buf, sep) - - override def addString(buf: StringBuilder) = - self.addString(buf) - - override def copyToArray[B >: A](xs: Array[B], start: Int) = self.copyToArray(xs, start) - - override def isEmpty = self.isEmpty - - override def projection = self.projection - - override def hasDefiniteSize = self.hasDefiniteSize -} diff --git a/src/library/scala/Iterator.scala b/src/library/scala/Iterator.scala deleted file mode 100644 index b5092a2430..0000000000 --- a/src/library/scala/Iterator.scala +++ /dev/null @@ -1,778 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - - -import Predef._ -import collection.mutable.{Buffer, ListBuffer, ArrayBuffer} -import annotation.tailrec - -/** The <code>Iterator</code> object provides various functions for - * creating specialized iterators. - * - * @author Martin Odersky - * @author Matthias Zenger - * @version 1.2, 10/02/2007 - */ -object Iterator { - - val empty = new Iterator[Nothing] { - def hasNext: Boolean = false - def next(): Nothing = throw new NoSuchElementException("next on empty iterator") - } - - /** - * @param x the element - * @return the iterator with one single element - */ - def single[a](x: a) = new Iterator[a] { - private var hasnext = true - def hasNext: Boolean = hasnext - def next(): a = - if (hasnext) { hasnext = false; x } - else throw new NoSuchElementException("next on empty iterator") - } - - def fromValues[a](xs: a*) = xs.elements - - /** - * @param xs the array of elements - * @see also: RandomAccessSeq.elements and slice - */ - def fromArray[a](xs: Array[a]): Iterator[a] = - fromArray(xs, 0, xs.length) - - /** - * @param xs the array of elements - * @param start the start index - * @param length the length - * @see also: RandomAccessSeq.elements and slice - */ - @throws(classOf[NoSuchElementException]) - def fromArray[a](xs: Array[a], start: Int, length: Int): Iterator[a] = - new BufferedIterator.Advanced[a] { - private var i = start - val end = if (start + length < xs.length) start + length else xs.length - override def hasNext: Boolean = i < end - def next(): a = - if (hasNext) { val x = xs(i) ; i += 1 ; x } - else throw new NoSuchElementException("next on empty iterator") - - override protected def defaultPeek : a = throw new NoSuchElementException("no lookahead") - override def peekList(sz: Int): Seq[a] = - xs.slice(i, if (i + sz > xs.length) xs.length else i + sz) - } - - /** - * @param str the given string - * @return the iterator on <code>str</code> - * @deprecated replaced by <code>str.elements</code> - */ - @deprecated def fromString(str: String): Iterator[Char] = - new BufferedIterator.Advanced[Char] { - private var i = 0 - private val len = str.length() - override def hasNext = i < len - def next = { val c = str charAt i; i += 1; c } - - override protected def defaultPeek : Char = throw new NoSuchElementException - override def peekList(sz: Int): Seq[Char] = - str.substring(i, if (i + sz > str.length) str.length else i + sz) - } - - /** - * @param n the product arity - * @return the iterator on <code>Product<n></code>. - */ - def fromProduct(n: Product): Iterator[Any] = new Iterator[Any] { - private var c: Int = 0 - private val cmax = n.productArity - def hasNext = c < cmax - def next() = { val a = n productElement c; c += 1; a } - } - - /** - * @deprecated use <code>fromProduct</code> instead. - */ - @deprecated - def fromCaseClass(n: Product) = fromProduct(n) - - /** Create an iterator with elements - * <code>e<sub>n+1</sub> = e<sub>n</sub> + 1</code> - * where <code>e<sub>0</sub> = start</code> - * and <code>e<sub>i</sub> < end</code>. However, - * if <code>start ≥ end</code>, then it will return an empty range. - * - * @param start the start value of the iterator - * @param end the end value of the iterator - * @return the iterator with values in range <code>[start;end)</code>. - */ - def range(start: Int, end: Int): Iterator[Int] = range(start, end, 1) - - /** Create an iterator with elements - * <code>e<sub>n+1</sub> = e<sub>n</sub> + step</code> - * where <code>e<sub>0</sub> = start</code> - * and elements are in the range between <code>start</code> (inclusive) - * and <code>end</code> (exclusive) - * - * @param start the start value of the iterator - * @param end the end value of the iterator - * @param step the increment value of the iterator (must be positive or negative) - * @return the iterator with values in range <code>[start;end)</code>. - */ - @throws(classOf[NoSuchElementException]) - def range(start: Int, end: Int, step: Int) = new Iterator[Int] { - private var i = start - def hasNext: Boolean = (step <= 0 || i < end) && (step >= 0 || i > end) - def next(): Int = - if (hasNext) { val j = i; i += step; j } - else throw new NoSuchElementException("next on empty iterator") - } - - /** Create an iterator with elements - * <code>e<sub>n+1</sub> = step(e<sub>n</sub>)</code> - * where <code>e<sub>0</sub> = start</code> - * and elements are in the range between <code>start</code> (inclusive) - * and <code>end</code> (exclusive) - * - * @param start the start value of the iterator - * @param end the end value of the iterator - * @param step the increment function of the iterator, must be monotonically increasing or decreasing - * @return the iterator with values in range <code>[start;end)</code>. - */ - @throws(classOf[NoSuchElementException]) - def range(start: Int, end: Int, step: Int => Int) = new Iterator[Int] { - private val up = step(start) > start - private val down = step(start) < start - private var i = start - def hasNext: Boolean = (!up || i < end) && (!down || i > end) - def next(): Int = - if (hasNext) { val j = i; i = step(i); j } - else throw new NoSuchElementException("next on empty iterator") - } - - /** Create an iterator with elements - * <code>e<sub>n+1</sub> = e<sub>n</sub> + 1</code> - * where <code>e<sub>0</sub> = start</code>. - * - * @param start the start value of the iterator - * @return the iterator starting at value <code>start</code>. - */ - def from(start: Int): Iterator[Int] = from(start, 1) - - /** Create an iterator with elements - * <code>e<sub>n+1</sub> = e<sub>n</sub> + step</code> - * where <code>e<sub>0</sub> = start</code>. - * - * @param start the start value of the iterator - * @param step the increment value of the iterator - * @return the iterator starting at value <code>start</code>. - */ - def from(start: Int, step: Int): Iterator[Int] = from(start, {x:Int => x + step}) - - /** Create an iterator with elements - * <code>e<sub>n+1</sub> = step(e<sub>n</sub>)</code> - * where <code>e<sub>0</sub> = start</code>. - * - * @param start the start value of the iterator - * @param step the increment function of the iterator - * @return the iterator starting at value <code>start</code>. - */ - def from(start: Int, step: Int => Int): Iterator[Int] = new Iterator[Int] { - private var i = start - override def hasNext: Boolean = true - def next(): Int = { val j = i; i = step(i); j } - } - - /** Create an iterator that is the concantenation of all iterators - * returned by a given iterator of iterators. - * @param its The iterator which returns on each call to next - * a new iterator whose elements are to be concatenated to the result. - */ - def flatten[T](its: Iterator[Iterator[T]]): Iterator[T] = new Iterator[T] { - private var it = its.next - def hasNext: Boolean = { - while (!it.hasNext && its.hasNext) it = its.next - it.hasNext - } - def next(): T = - if (hasNext) it.next - else empty.next() - } -} - -/** Iterators are data structures that allow to iterate over a sequence - * of elements. They have a <code>hasNext</code> method for checking - * if there is a next element available, and a <code>next</code> method - * which returns the next element and discards it from the iterator. - * - * @author Martin Odersky, Matthias Zenger - * @version 1.2, 15/03/2004 - */ -trait Iterator[+A] { - - /** Does this iterator provide another element? - */ - def hasNext: Boolean - - /** Returns the next element. - */ - def next(): A - - - /** Returns a new iterator that iterates only over the first <code>n</code> - * elements. - * - * @param n the number of elements to take - * @return the new iterator - */ - @throws(classOf[NoSuchElementException]) - def take(n: Int): Iterator[A] = new Iterator[A] { - var remaining = n - def hasNext = remaining > 0 && Iterator.this.hasNext - def next(): A = - if (hasNext) { remaining -= 1; Iterator.this.next } - else throw new NoSuchElementException("next on empty iterator") - } - - /** Removes the first <code>n</code> elements from this iterator. - * - * @param n the number of elements to drop - * @return the new iterator - */ - def drop(n: Int): Iterator[A] = { - @tailrec - def loop(left: Int): Iterator[A] = - if (left > 0 && hasNext) { next; loop(left - 1) } - else this - - loop(n) - } - - /** A sub-iterator of <code>until - from elements - * starting at index <code>from</code> - * - * @param from The index of the first element of the slice - * @param until The index of the element following the slice - */ - def slice(from: Int, until: Int): Iterator[A] = drop(from).take(until - from) - - /** Returns a new iterator that maps all elements of this iterator - * to new elements using function <code>f</code>. - */ - def map[B](f: A => B): Iterator[B] = new Iterator[B] { - def hasNext = Iterator.this.hasNext - def next() = f(Iterator.this.next) - } - - /** Returns a new iterator that first yields the elements of this - * iterator followed by the elements provided by iterator <code>that</code>. - * @deprecated use <code>++</code> - */ - def append[B >: A](that: Iterator[B]) = new Iterator[B] { - def hasNext = Iterator.this.hasNext || that.hasNext - def next() = if (Iterator.this.hasNext) Iterator.this.next else that.next - } - - /** Returns a new iterator that first yields the elements of this - * iterator followed by the elements provided by iterator <code>that</code>. - */ - def ++[B >: A](that: => Iterator[B]) = new Iterator[B] { - // optimize a little bit to prevent n log n behavior. - var what : Iterator[B] = Iterator.this - def hasNext = if (what.hasNext) true - else if (what eq Iterator.this) { - what = that - what.hasNext - } else false - - def next = { hasNext; what.next } - } - - /** Applies the given function <code>f</code> to each element of - * this iterator, then concatenates the results. - * - * @param f the function to apply on each element. - * @return an iterator over <code>f(a<sub>0</sub>), ... , - * f(a<sub>n</sub>)</code> if this iterator yields the - * elements <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. - */ - @throws(classOf[NoSuchElementException]) - def flatMap[B](f: A => Iterator[B]): Iterator[B] = new Iterator[B] { - private var cur: Iterator[B] = Iterator.empty - def hasNext: Boolean = - if (cur.hasNext) true - else if (Iterator.this.hasNext) { - cur = f(Iterator.this.next) - hasNext - } else false - def next(): B = - if (cur.hasNext) cur.next - else if (Iterator.this.hasNext) { - cur = f(Iterator.this.next) - next - } else throw new NoSuchElementException("next on empty iterator") - } - - protected class PredicatedIterator(p : A => Boolean) extends BufferedIterator.Default[A] { - protected def doEnd : Boolean = false - protected override def fill(sz: Int): Seq[A] = { - while (true) { - if (!Iterator.this.hasNext) return Nil - val ret = Iterator.this.next - if (p(ret)) return ret :: Nil - if (doEnd) return Nil - } - throw new Error - } - } - protected class TakeWhileIterator(p : A => Boolean) extends PredicatedIterator(p) { - private var ended = false - override protected def doEnd = { - ended = true; true - } - override protected def fill(sz : Int) : Seq[A] = - if (ended) Nil else super.fill(sz) - } - - - /** Returns an iterator over all the elements of this iterator that - * satisfy the predicate <code>p</code>. The order of the elements - * is preserved. - * - * @param p the predicate used to filter the iterator. - * @return the elements of this iterator satisfying <code>p</code>. - */ - def filter(p: A => Boolean): Iterator[A] = new PredicatedIterator(p) - - /** Returns an iterator over the longest prefix of this iterator such that - * all elements of the result satisfy the predicate <code>p</code>. - * The order of the elements is preserved. - * - * The behavior of <code>this</code> iterator is undefined after this method invocation. - * - * @param p the predicate used to filter the iterator. - * @return the longest prefix of this iterator satisfying <code>p</code>. - */ - def takeWhile(p: A => Boolean): Iterator[A] = new TakeWhileIterator(p) - - /** Skips longest sequence of elements of this iterator which satisfy given - * predicate <code>p</code>, and returns an iterator of the remaining elements. - * - * The behavior of <code>this</code> iterator is undefined after this method invocation. - * - * @param p the predicate used to skip elements. - * @return an iterator consisting of the remaining elements - */ - def dropWhile(p: A => Boolean): Iterator[A] = { - @tailrec - def loop(): Iterator[A] = - if (hasNext) { - val x = next - if (p(x)) loop() - else Iterator.single(x) append this - } - else this - - loop() - } - - /** Return an iterator formed from this iterator and the specified iterator - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * If one of the two iterators is longer than the other, its remaining elements are ignored. - * - * @return an iterator yielding <code>{a<sub>0</sub>,b<sub>0</sub>}, - * {a<sub>1</sub>,b<sub>1</sub>}, ...</code> where - * <code>a<sub>i</sub></code> are the elements from this iterator - * and <code>b<sub>i</sub></code> are the elements from iterator - * <code>that</code>. - */ - def zip[B](that: Iterator[B]) = new Iterator[(A, B)] { - def hasNext = Iterator.this.hasNext && that.hasNext - def next = (Iterator.this.next, that.next) - } - - /** Return an iterator that pairs each element of this iterator - * with its index, counting from 0. - * - * @return an iterator yielding <code>{a<sub>0</sub>,0}, - * {a<sub>1</sub>,1}...</code> where <code>a<sub>i</sub></code> - * are the elements from this iterator. - */ - def zipWithIndex = new Iterator[(A, Int)] { - var idx = 0 - def hasNext = Iterator.this.hasNext - def next = { - val ret = (Iterator.this.next, idx) - idx += 1 - ret - } - } - - /** Apply a function <code>f</code> to all elements of this - * iterable object. - * - * @param f a function that is applied to every element. - */ - def foreach(f: A => Unit) { while (hasNext) f(next) } - - /** Apply a predicate <code>p</code> to all elements of this - * iterable object and return <code>true</code> iff the predicate yields - * <code>true</code> for all elements. - * - * @param p the predicate - * @return <code>true</code> iff the predicate yields <code>true</code> - * for all elements. - */ - def forall(p: A => Boolean): Boolean = { - var res = true - while (res && hasNext) res = p(next) - res - } - - /** Apply a predicate <code>p</code> to all elements of this - * iterable object and return true, iff there is at least one - * element for which <code>p</code> yields <code>true</code>. - * - * @param p the predicate - * @return <code>true</code> iff the predicate yields <code>true</code> - * for at least one element. - */ - def exists(p: A => Boolean): Boolean = { - var res = false - while (!res && hasNext) res = p(next) - res - } - - /** Tests if the given value <code>elem</code> is a member of this iterator. - * - * @param elem element whose membership has to be tested. - * @return <code>true</code> iff there is an element of this iterator which - * is equal (w.r.t. <code>==</code>) to <code>elem</code>. - */ - def contains(elem: Any): Boolean = exists { _ == elem } - - /** Find and return the first element of the iterable object satisfying a - * predicate, if any. - * - * @param p the predicate - * @return the first element in the iterable object satisfying - * <code>p</code>, or <code>None</code> if none exists. - */ - def find(p: A => Boolean): Option[A] = { - var res: Option[A] = None - while (res.isEmpty && hasNext) { - val e = next - if (p(e)) res = Some(e) - } - res - } - - /** Returns index of the first element satisying a predicate, or -1. - * - * @note may not terminate for infinite-sized collections. - * @param p the predicate - * @return the index of the first element satisfying <code>p</code>, - * or -1 if such an element does not exist - */ - def findIndexOf(p: A => Boolean): Int = { - var i = 0 - var found = false - while (!found && hasNext) { - if (p(next)) { - found = true - } else { - i += 1 - } - } - if (found) i else -1 - } - - /** Returns the index of the first occurence of the specified - * object in this iterable object. - * - * @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. - */ - def indexOf[B >: A](elem: B): Int = { - var i = 0 - var found = false - while (!found && hasNext) { - if (next == elem) { - found = true - } else { - i += 1 - } - } - if (found) i else -1 - } - - /** Combines the elements of this iterator together using the binary - * operator <code>op</code>, from left to right, and starting with - * the value <code>z</code>. - * - * @return <code>op(... (op(op(z,a<sub>0</sub>),a<sub>1</sub>) ...), - * a<sub>n</sub>)</code> if the iterator yields elements - * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>. - */ - def foldLeft[B](z: B)(op: (B, A) => B): B = { - var acc = z - while (hasNext) acc = op(acc, next) - acc - } - - /** Combines the elements of this iterator together using the binary - * operator <code>op</code>, from right to left, and starting with - * the value <code>z</code>. - * - * @return <code>a<sub>0</sub> op (... op (a<sub>n</sub> op z)...)</code> - * if the iterator yields elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., - * a<sub>n</sub></code>. - */ - def foldRight[B](z: B)(op: (A, B) => B): B = { - def fold(z: B): B = if (hasNext) op(next, fold(z)) else z - fold(z) - } - - /** Similar to <code>foldLeft</code> but can be used as - * an operator with the order of iterator and zero arguments reversed. - * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code>. - * - * @param z the left argument of the first application of <code>op</code> - * (evaluation occurs from left to right). - * @param op the applied operator. - * @return the result value - * @see <code><a href="#foldLeft">foldLeft</a></code>. - */ - def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op) - - /** An alias for <code>foldRight</code>. - * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code>. - * - * @param z the right argument of the first application of <code>op</code> - * (evaluation occurs from right to left). - * @param op the applied operator. - * @return the result value. - * @see <code><a href="#foldRight">foldRight</a></code>. - */ - def :\[B](z: B)(op: (A, B) => B): B = foldRight(z)(op) - - /** Combines the elements of this iterator together using the binary - * operator <code>op</code>, from left to right - * @param op The operator to apply - * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code> - if the iterator yields elements - * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>. - * @throws Predef.UnsupportedOperationException if the iterator is empty. - */ - @throws(classOf[UnsupportedOperationException]) - def reduceLeft[B >: A](op: (B, A) => B): B = { - if (hasNext) foldLeft[B](next)(op) - else throw new UnsupportedOperationException("empty.reduceLeft") - } - - /** Combines the elements of this iterator together using the binary - * operator <code>op</code>, from right to left - * @param op The operator to apply - * - * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code> - * if the iterator yields elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., - * a<sub>n</sub></code>. - - * @throws Predef.UnsupportedOperationException if the iterator is empty. - */ - @throws(classOf[UnsupportedOperationException]) - def reduceRight[B >: A](op: (A, B) => B): B = { - if (!hasNext) throw new UnsupportedOperationException("empty.reduceRight") - val x = next - if (hasNext) op(x, reduceRight(op)) - else x - } - - /** Returns a buffered iterator from this iterator. - */ - def buffered: BufferedIterator[A] = new BufferedIterator.Default[A] { - protected def fill(sz : Int) = if (Iterator.this.hasNext) (Iterator.this.next) :: Nil else Nil - } - - /** Returns a counted iterator from this iterator. - */ - def counted = new CountedIterator[A] { - private var cnt = -1 - def count = cnt - def hasNext: Boolean = Iterator.this.hasNext - def next(): A = { cnt += 1; Iterator.this.next } - } - - /** Creates two new iterators that both iterate over the same elements - * than this iterator (in the same order). - * - * @return a pair of iterators - */ - def duplicate: (Iterator[A], Iterator[A]) = { - var xs: List[A] = Nil - var ahead: Iterator[A] = null - class Partner extends Iterator[A] { - var ys: List[A] = Nil - def hasNext: Boolean = Iterator.this.synchronized ( - ((this == ahead) && Iterator.this.hasNext) || - ((this != ahead) && (!xs.isEmpty || !ys.isEmpty || Iterator.this.hasNext)) - ) - def next(): A = Iterator.this.synchronized { - if (this == ahead) { - val e = Iterator.this.next - xs = e :: xs; e - } else { - if (ys.isEmpty) { - ys = xs.reverse - xs = Nil - } - ys match { - case Nil => - val e = Iterator.this.next - ahead = this - xs = e :: xs; e - case z :: zs => - ys = zs; z - } - } - } - } - ahead = new Partner - (ahead, new Partner) - } - - /** Fills the given array <code>xs</code> with the elements of - * this sequence starting at position <code>start</code>. - * - * @param xs the array to fill. - * @param start the starting index. - * @pre the array must be large enough to hold all elements. - */ - def copyToArray[B >: A](xs: Array[B], start: Int) { - var i = start - while (hasNext) { - xs(i) = next - i += 1 - } - } - /** Fills the given array <code>xs</code> with the elements of - * this sequence starting at position <code>start</code>. Like <code>copyToArray</code>, - * but designed to accomodate IO stream operations. - * - * @param xs the array to fill. - * @param start the starting index. - * @param sz the maximum number of elements to be read. - * @pre the array must be large enough to hold <code>sz</code> elements. - */ - def readInto[B >: A](xs: Array[B], start: Int, sz: Int) { - var i = start - while (hasNext && i - start < sz) { - xs(i) = next - i += 1 - } - } - def readInto[B >: A](xs: Array[B], start: Int) { - readInto(xs, start, xs.length - start) - } - def readInto[B >: A](xs: Array[B]) { - readInto(xs, 0, xs.length) - } - - /** Copy all elements to a buffer - * @param The buffer to which elements are copied - * @return The buffer to which elements are copied - */ - def copyToBuffer[B >: A](dest: Buffer[B]) { - while (hasNext) dest += next - } - - /** Transform this iterator into a list of all elements. - * - * @return a list which enumerates all elements of this iterator. - */ - def toList: List[A] = { - val res = new ListBuffer[A] - while (hasNext) res += next - res.toList - } - - /** Collect elements into a seq. - * - * @return a seq which enumerates all elements of this iterator. - */ - def collect: Seq[A] = { - val buffer = new ArrayBuffer[A] - this copyToBuffer buffer - buffer.readOnly - } - - /** Returns a string representation of the elements in this iterator. The resulting string - * begins with the string <code>start</code> and is finished by the string - * <code>end</code>. Inside, the string representations of elements (w.r.t. - * the method <code>toString()</code>) are separated by the string - * <code>sep</code>. - * <p/> - * Ex: <br/> - * <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code> - * - * @param start starting string. - * @param sep separator string. - * @param end ending string. - * @return a string representation of this iterable object. - */ - def mkString(start: String, sep: String, end: String): String = { - val buf = new StringBuilder - addString(buf, start, sep, end).toString - } - - /** Returns a string representation of this iterable object. The string - * representations of elements (w.r.t. the method <code>toString()</code>) - * are separated by the string <code>sep</code>. - * - * @param sep separator string. - * @return a string representation of this iterable object. - */ - def mkString(sep: String): String = this.mkString("", sep, "") - - /** Returns a string representation of this iterable object. The string - * representations of elements (w.r.t. the method <code>toString()</code>) - * are separated by a comma. - * - * @return a string representation of this iterable object. - */ - def mkString: String = - mkString("") - - /** Write all elements of this string into given string builder. - * - * @param buf ... - * @param start the starting string - * @param sep the separator string - * @param end the ending string - * @return ... - */ - def addString(buf: StringBuilder, start: String, sep: String, end: String): StringBuilder = { - buf.append(start) - val elems = this - if (elems.hasNext) buf.append(elems.next) - while (elems.hasNext) { - buf.append(sep); buf.append(elems.next) - } - buf.append(end) - } - override def toString = (if (hasNext) "non-empty" else "empty")+" iterator" -} diff --git a/src/library/scala/List.scala b/src/library/scala/List.scala deleted file mode 100644 index 8b25050de3..0000000000 --- a/src/library/scala/List.scala +++ /dev/null @@ -1,1459 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - -import scala.collection.mutable.{ListBuffer, LinkedHashMap} -import annotation.tailrec -import Predef._ - -/** This object provides methods for creating specialized lists, and for - * transforming special kinds of lists (e.g. lists of lists). - * - * @author Martin Odersky and others - * @version 1.0, 15/07/2003 - */ -object List { - - /** Create a list with given elements. - * - * @param xs the elements to put in the list - * @return the list containing elements xs. - */ - def apply[A](xs: A*): List[A] = xs.toList - - /** for unapply matching - */ - def unapplySeq[A](x: List[A]): Some[List[A]] = Some(x) - - /** Create a sorted list of all integers in a range. - * - * @param from the start value of the list - * @param end the end value of the list - * @return the sorted list of all integers in range [from;end). - */ - def range(start: Int, end: Int): List[Int] = - range(start, end, 1) - - /** Create a list with element values - * <code>v<sub>n+1</sub> = v<sub>n</sub> + step</code> - * where <code>v<sub>0</sub> = start</code> - * and elements are in the range between <code>start</code> (inclusive) - * and <code>end</code> (exclusive) - * - * @param start the start value of the list - * @param end the end value of the list - * @param step the increment value of the list - * @return the sorted list of all integers in range [start;end). - */ - def range(start: Int, end: Int, step: Int): List[Int] = { - if (step == 0) - throw new IllegalArgumentException("step is zero") - val b = new ListBuffer[Int] - var i = start - while ((step <= 0 || i < end) && (step >= 0 || i > end)) { - b += i - i += step - } - b.toList - } - - /** Create a sorted list with element values - * <code>v<sub>n+1</sub> = step(v<sub>n</sub>)</code> - * where <code>v<sub>0</sub> = start</code> - * and elements are in the range between <code>start</code> (inclusive) - * and <code>end</code> (exclusive) - * - * @param start the start value of the list - * @param end the end value of the list - * @param step the increment function of the list, which given <code>v<sub>n</sub></code>, - * computes <code>v<sub>n+1</sub></code>. Must be monotonically increasing - * or decreasing. - * @return the sorted list of all integers in range [start;end). - */ - def range(start: Int, end: Int, step: Int => Int): List[Int] = { - val up = step(start) > start - val down = step(start) < start - val b = new ListBuffer[Int] - var i = start - while ((!up || i < end) && (!down || i > end)) { - b += i - val next = step(i) - if (i == next) - throw new IllegalArgumentException("the step function did not make any progress on "+ i) - i = next - } - b.toList - } - - /** Create a list containing several copies of an element. - * - * @param n the length of the resulting list - * @param elem the element composing the resulting list - * @return a list composed of n elements all equal to elem - */ - def make[A](n: Int, elem: A): List[A] = { - val b = new ListBuffer[A] - var i = 0 - while (i < n) { - b += elem - i += 1 - } - b.toList - } - - /** Create a list by applying a function to successive integers. - * - * @param n the length of the resulting list - * @param maker the procedure which, given an integer <code>n</code>, - * returns the nth element of the resulting list, where - * <code>n</code> is in interval <code>[0;n)</code>. - * @return the list obtained by applying the maker function to - * successive integers from 0 to n (exclusive). - */ - def tabulate[A](n: Int, maker: Int => A): List[A] = { - val b = new ListBuffer[A] - var i = 0 - while (i < n) { - b += maker(i) - i += 1 - } - b.toList - } - - /** Concatenate all the elements of a given list of lists. - * - * @param xss the list of lists that are to be concatenated - * @return the concatenation of all the lists - */ - def flatten[A](xss: List[List[A]]): List[A] = concat(xss: _*) - - /** Concatenate all the argument lists into a single list. - * - * @param xss the lists that are to be concatenated - * @return the concatenation of all the lists - */ - def concat[A](xss: List[A]*): List[A] = { - val b = new ListBuffer[A] - for (xs <- xss) { - var xc = xs - while (!xc.isEmpty) { - b += xc.head - xc = xc.tail - } - } - b.toList - } - - /** Transforms a list of pairs into a pair of lists. - * - * @param xs the list of pairs to unzip - * @return a pair of lists. - */ - def unzip[A,B](xs: List[(A,B)]): (List[A], List[B]) = { - val b1 = new ListBuffer[A] - val b2 = new ListBuffer[B] - var xc = xs - while (!xc.isEmpty) { - b1 += xc.head._1 - b2 += xc.head._2 - xc = xc.tail - } - (b1.toList, b2.toList) - } - - /** Transforms an iterable of pairs into a pair of lists. - * - * @param xs the iterable of pairs to unzip - * @return a pair of lists. - */ - def unzip[A,B](xs: Iterable[(A,B)]): (List[A], List[B]) = - xs.foldRight[(List[A], List[B])]((Nil, Nil)) { - case ((x, y), (xs, ys)) => (x :: xs, y :: ys) - } - - /** - * Returns the <code>Left</code> values in the given <code>Iterable</code> of <code>Either</code>s. - */ - def lefts[A, B](es: Iterable[Either[A, B]]) = - es.foldRight[List[A]](Nil)((e, as) => e match { - case Left(a) => a :: as - case Right(_) => as - }) - - /** - * Returns the <code>Right</code> values in the given<code>Iterable</code> of <code>Either</code>s. - */ - def rights[A, B](es: Iterable[Either[A, B]]) = - es.foldRight[List[B]](Nil)((e, bs) => e match { - case Left(_) => bs - case Right(b) => b :: bs - }) - - /** Transforms an Iterable of Eithers into a pair of lists. - * - * @param xs the iterable of Eithers to separate - * @return a pair of lists. - */ - def separate[A,B](es: Iterable[Either[A,B]]): (List[A], List[B]) = - es.foldRight[(List[A], List[B])]((Nil, Nil)) { - case (Left(a), (lefts, rights)) => (a :: lefts, rights) - case (Right(b), (lefts, rights)) => (lefts, b :: rights) - } - - /** Converts an iterator to a list. - * - * @param it the iterator to convert - * @return a list that contains the elements returned by successive - * calls to <code>it.next</code> - */ - def fromIterator[A](it: Iterator[A]): List[A] = it.toList - - /** Converts an array into a list. - * - * @param arr the array to convert - * @return a list that contains the same elements than <code>arr</code> - * in the same order - */ - def fromArray[A](arr: Array[A]): List[A] = fromArray(arr, 0, arr.length) - - /** Converts a range of an array into a list. - * - * @param arr the array to convert - * @param start the first index to consider - * @param len the lenght of the range to convert - * @return a list that contains the same elements than <code>arr</code> - * in the same order - */ - def fromArray[A](arr: Array[A], start: Int, len: Int): List[A] = { - var res: List[A] = Nil - var i = start + len - while (i > start) { - i -= 1 - res = arr(i) :: res - } - res - } - - /** Parses a string which contains substrings separated by a - * separator character and returns a list of all substrings. - * - * @param str the string to parse - * @param separator the separator character - * @return the list of substrings - */ - def fromString(str: String, separator: Char): List[String] = { - var words: List[String] = Nil - var pos = str.length() - while (pos > 0) { - val pos1 = str.lastIndexOf(separator, pos - 1) - if (pos1 + 1 < pos) - words = str.substring(pos1 + 1, pos) :: words - pos = pos1 - } - words - } - - /** Returns the given string as a list of characters. - * - * @param str the string to convert. - * @return the string as a list of characters. - * @deprecated use <code>str.toList</code> instead - */ - @deprecated def fromString(str: String): List[Char] = - str.toList - - /** Returns the given list of characters as a string. - * - * @param xs the list to convert. - * @return the list in form of a string. - */ - def toString(xs: List[Char]): String = { - val sb = new StringBuilder() - var xc = xs - while (!xc.isEmpty) { - sb.append(xc.head) - xc = xc.tail - } - sb.toString() - } - - /** Like xs map f, but returns <code>xs</code> unchanged if function - * <code>f</code> maps all elements to themselves. - * - * @param xs ... - * @param f ... - * @return ... - */ - def mapConserve[A <: AnyRef](xs: List[A])(f: A => A): List[A] = { - def loop(ys: List[A]): List[A] = - if (ys.isEmpty) xs - else { - val head0 = ys.head - val head1 = f(head0) - if (head1 eq head0) { - loop(ys.tail) - } else { - val ys1 = head1 :: mapConserve(ys.tail)(f) - if (xs eq ys) ys1 - else { - val b = new ListBuffer[A] - var xc = xs - while (xc ne ys) { - b += xc.head - xc = xc.tail - } - b.prependToList(ys1) - } - } - } - loop(xs) - } - - /** Returns the list resulting from applying the given function <code>f</code> - * to corresponding elements of the argument lists. - * - * @param f function to apply to each pair of elements. - * @return <code>[f(a0,b0), ..., f(an,bn)]</code> if the lists are - * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and - * <code>n = min(k,l)</code> - */ - def map2[A,B,C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = { - val b = new ListBuffer[C] - var xc = xs - var yc = ys - while (!xc.isEmpty && !yc.isEmpty) { - b += f(xc.head, yc.head) - xc = xc.tail - yc = yc.tail - } - b.toList - } - - /** Returns the list resulting from applying the given function - * <code>f</code> to corresponding elements of the argument lists. - * - * @param f function to apply to each pair of elements. - * @return <code>[f(a<sub>0</sub>,b<sub>0</sub>,c<sub>0</sub>), - * ..., f(a<sub>n</sub>,b<sub>n</sub>,c<sub>n</sub>)]</code> - * if the lists are <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>, - * <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code>, - * <code>[c<sub>0</sub>, ..., c<sub>m</sub>]</code> and - * <code>n = min(k,l,m)</code> - */ - def map3[A,B,C,D](xs: List[A], ys: List[B], zs: List[C])(f: (A, B, C) => D): List[D] = { - val b = new ListBuffer[D] - var xc = xs - var yc = ys - var zc = zs - while (!xc.isEmpty && !yc.isEmpty && !zc.isEmpty) { - b += f(xc.head, yc.head, zc.head) - xc = xc.tail - yc = yc.tail - zc = zc.tail - } - b.toList - } - - /** Tests whether the given predicate <code>p</code> holds - * for all corresponding elements of the argument lists. - * - * @param p function to apply to each pair of elements. - * @return <code>(p(a<sub>0</sub>,b<sub>0</sub>) && - * ... && p(a<sub>n</sub>,b<sub>n</sub>))]</code> - * if the lists are <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>; - * <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code> - * and <code>n = min(k,l)</code> - */ - def forall2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = { - var xc = xs - var yc = ys - while (!xc.isEmpty && !yc.isEmpty) { - if (!f(xc.head, yc.head)) return false - xc = xc.tail - yc = yc.tail - } - true - } - - /** Tests whether the given predicate <code>p</code> holds - * for some corresponding elements of the argument lists. - * - * @param p function to apply to each pair of elements. - * @return <code>n != 0 && (p(a<sub>0</sub>,b<sub>0</sub>) || - * ... || p(a<sub>n</sub>,b<sub>n</sub>))]</code> if the lists are - * <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>, - * <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code> and - * <code>n = min(k,l)</code> - */ - def exists2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = { - var xc = xs - var yc = ys - while (!xc.isEmpty && !yc.isEmpty) { - if (f(xc.head, yc.head)) return true - xc = xc.tail - yc = yc.tail - } - false - } - - /** Transposes a list of lists. - * pre: All element lists have the same length. - * - * @param xss the list of lists - * @return the transposed list of lists - */ - def transpose[A](xss: List[List[A]]): List[List[A]] = { - val buf = new ListBuffer[List[A]] - var yss = xss - while (!yss.head.isEmpty) { - buf += (yss map (_.head)) - yss = (yss map (_.tail)) - } - buf.toList - } - - /** Lists with ordered elements are ordered - implicit def list2ordered[a <% Ordered[a]](x: List[a]): Ordered[List[a]] = new Ordered[List[a]] { - def compare [b >: List[a] <% Ordered[b]](y: b): Int = y match { - case y1: List[a] => compareLists(x, y1); - case _ => -(y compare x) - } - private def compareLists(xs: List[a], ys: List[a]): Int = { - if (xs.isEmpty && ys.isEmpty) 0 - else if (xs.isEmpty) -1 - else if (ys.isEmpty) 1 - else { - val s = xs.head compare ys.head; - if (s != 0) s - else compareLists(xs.tail, ys.tail) - } - } - } - */ -} - -/** A class representing an ordered collection of elements of type - * <code>a</code>. This class comes with two implementing case - * classes <code>scala.Nil</code> and <code>scala.::</code> that - * implement the abstract members <code>isEmpty</code>, - * <code>head</code> and <code>tail</code>. - * - * @author Martin Odersky and others - * @version 1.0, 16/07/2003 - */ -sealed abstract class List[+A] extends Seq[A] with Product { - - /** Returns true if the list does not contain any elements. - * @return <code>true</code>, iff the list is empty. - */ - override def isEmpty: Boolean - - /** Returns this first element of the list. - * - * @return the first element of this list. - * @throws Predef.NoSuchElementException if the list is empty. - */ - def head: A - - /** Result of comparing <code>length</code> with operand <code>l</code>. - * returns <code>x</code> where - * <code>x < 0</code> iff <code>this.length < l</code> - * <code>x == 0</code> iff <code>this.length == l</code> - * <code>x > 0</code> iff <code>this.length > that</code>. - * - * This method is used by matching streams against right-ignoring (...,_*) patterns. - * - * This method does not call <code>List.length</code>, it works for <code>O(l)</code>, - * not for <code>O(length)</code>. - */ - override def lengthCompare(l: Int) = { - if (isEmpty) 0 - l - else if (l <= 0) 1 - else tail.lengthCompare(l - 1) - } - - /** Returns this list without its first element. - * - * @return this list without its first element. - * @throws Predef.NoSuchElementException if the list is empty. - */ - def tail: List[A] - - /** <p> - * Add an element <code>x</code> at the beginning of this list. - * </p> - * - * @param x the element to prepend. - * @return the list with <code>x</code> added at the beginning. - * @ex <code>1 :: List(2, 3) = List(2, 3).::(1) = List(1, 2, 3)</code> - */ - def ::[B >: A] (x: B): List[B] = - new scala.::(x, this) - - /** <p> - * Add an element <code>x</code> at the end of this list. - * </p> - * - * @deprecated Replace uses of <code>l + e</code> with <code>l ::: List(e)</code>. - * - * @param x the element to append. - * @return the list with <code>x</code> added at the end. - */ - @deprecated def +[B >: A](x: B): List[B] = - if (isEmpty) List(x) - else { - val buf = new ListBuffer[B] - this copyToBuffer buf - buf += x - buf.toList - } - - /** <p> - * Returns a list resulting from the concatenation of the given - * list <code>prefix</code> and this list. - * </p> - * - * @param prefix the list to concatenate at the beginning of this list. - * @return the concatenation of the two lists. - * @ex <code>List(1, 2) ::: List(3, 4) = List(3, 4).:::(List(1, 2)) = List(1, 2, 3, 4)</code> - */ - def :::[B >: A](prefix: List[B]): List[B] = - if (isEmpty) prefix - else { - val b = new ListBuffer[B] - var those = prefix - while (!those.isEmpty) { - b += those.head - those = those.tail - } - b.prependToList(this) - } - - /** Appends two list objects. - */ - override def ++[B >: A](that: Iterable[B]): List[B] = - this ::: that.toList - - /** Reverse the given prefix and append the current list to that. - * This function is equivalent to an application of <code>reverse</code> - * on the prefix followed by a call to <code>:::</code>, but more - * efficient. - * - * @param prefix the prefix to reverse and then prepend - * @return the concatenation of the reversed prefix and the current list. - */ - def reverse_:::[B >: A](prefix: List[B]): List[B] = { - var these: List[B] = this - var pres = prefix - while (!pres.isEmpty) { - these = pres.head :: these - pres = pres.tail - } - these - } - - /** Returns the number of elements in the list. - * - * @return the number of elements in the list. - */ - def length: Int = { - var these = this - var len = 0 - while (!these.isEmpty) { - len += 1 - these = these.tail - } - len - } - - /** Creates a list with all indices in the list. This is - * equivalent to a call to <code>List.range(0, xs.length)</code>. - * - * @return a list of all indices in the list. - */ - def indices: List[Int] = { - val b = new ListBuffer[Int] - var i = 0 - var these = this - while (!these.isEmpty) { - b += i - i += 1 - these = these.tail - } - b.toList - } - - /** Returns the elements in the list as an iterator - * - * @return an iterator on the list elements. - */ - override def elements: Iterator[A] = new Iterator[A] { - var these = List.this - def hasNext: Boolean = !these.isEmpty - def next: A = - if (!hasNext) - throw new NoSuchElementException("next on empty Iterator") - else { - val result = these.head; these = these.tail; result - } - override def toList: List[A] = these - } - - /** Overrides the method in Iterable for efficiency. - * - * @return the list itself - */ - override def toList: List[A] = this - - /** Returns the list without its last element. - * - * @return the list without its last element. - * @throws Predef.UnsupportedOperationException if the list is empty. - */ - def init: List[A] = - if (isEmpty) throw new UnsupportedOperationException("Nil.init") - else { - val b = new ListBuffer[A] - var elem = head - var next = tail - while (!next.isEmpty) { - b += elem - elem = next.head - next = next.tail - } - b.toList - } - - /** Returns the last element of this list. - * - * @return the last element of the list. - * @throws Predef.NoSuchElementException if the list is empty. - */ - override def last: A = - if (isEmpty) throw new Predef.NoSuchElementException("Nil.last") - else { - var cur = this - var next = this.tail - while (!next.isEmpty) { - cur = next - next = next.tail - } - cur.head - } - - /** Returns the <code>n</code> first elements of this list, or else the whole - * list, if it has less than <code>n</code> elements. - * - * @param n the number of elements to take. - * @return the <code>n</code> first elements of this list. - */ - override def take(n: Int): List[A] = { - val b = new ListBuffer[A] - var i = 0 - var these = this - while (!these.isEmpty && i < n) { - i += 1 - b += these.head - these = these.tail - } - if (these.isEmpty) this - else b.toList - } - - /** Returns the list with elements belonging to the given index range. - * - * @param start the start position of the list slice. - * @param end the end position (exclusive) of the list slice. - * @return the list with elements belonging to the given index range. - */ - override def slice(start: Int, end: Int): List[A] = { - val s = start max 0 - val e = end min this.length - drop(s) take (e - s) - } - - /** Returns the list without its <code>n</code> first elements. - * If this list has less than <code>n</code> elements, the empty list is returned. - * - * @param n the number of elements to drop. - * @return the list without its <code>n</code> first elements. - */ - override def drop(n: Int): List[A] = { - var these = this - var count = n - while (!these.isEmpty && count > 0) { - these = these.tail - count -= 1 - } - these - } - - /** Returns the rightmost <code>n</code> elements from this list. - * - * @param n the number of elements to take - * @return the suffix of length <code>n</code> of the list - */ - def takeRight(n: Int): List[A] = { - @tailrec - def loop(lead: List[A], lag: List[A]): List[A] = lead match { - case Nil => lag - case _ :: tail => loop(tail, lag.tail) - } - loop(drop(n), this) - } - - /** Returns the list wihout its rightmost <code>n</code> elements. - * - * @param n the number of elements to take - * @return the list without its rightmost <code>n</code> elements - */ - def dropRight(n: Int): List[A] = { - def loop(lead: List[A], lag: List[A]): List[A] = lead match { - case Nil => Nil - case _ :: tail => lag.head :: loop(tail, lag.tail) - } - loop(drop(n), this) - } - - /** Split the list at a given point and return the two parts thus - * created. - * - * @param n the position at which to split - * @return a pair of lists composed of the first <code>n</code> - * elements, and the other elements. - */ - def splitAt(n: Int): (List[A], List[A]) = { - val b = new ListBuffer[A] - var i = 0 - var these = this - while (!these.isEmpty && i < n) { - i += 1 - b += these.head - these = these.tail - } - (b.toList, these) - } - - /** Returns the longest prefix of this list whose elements satisfy - * the predicate <code>p</code>. - * - * @param p the test predicate. - * @return the longest prefix of this list whose elements satisfy - * the predicate <code>p</code>. - */ - override def takeWhile(p: A => Boolean): List[A] = { - val b = new ListBuffer[A] - var these = this - while (!these.isEmpty && p(these.head)) { - b += these.head - these = these.tail - } - b.toList - } - - /** Returns the longest suffix of this list whose first element - * does not satisfy the predicate <code>p</code>. - * - * @param p the test predicate. - * @return the longest suffix of the list whose first element - * does not satisfy the predicate <code>p</code>. - */ - override def dropWhile(p: A => Boolean): List[A] = { - @tailrec - def loop(xs: List[A]): List[A] = - if (xs.isEmpty || !p(xs.head)) xs - else loop(xs.tail) - - loop(this) - } - - /** Returns the longest prefix of the list whose elements all satisfy - * the given predicate, and the rest of the list. - * - * @param p the test predicate - * @return a pair consisting of the longest prefix of the list whose - * elements all satisfy <code>p</code>, and the rest of the list. - */ - def span(p: A => Boolean): (List[A], List[A]) = { - val b = new ListBuffer[A] - var these = this - while (!these.isEmpty && p(these.head)) { - b += these.head - these = these.tail - } - (b.toList, these) - } - - /** Like <code>span</code> but with the predicate inverted. - */ - def break(p: A => Boolean): (List[A], List[A]) = span { x => !p(x) } - - /** Returns the <code>n</code>-th element of this list. The first element - * (head of the list) is at position 0. - * - * @param n index of the element to return - * @return the element at position <code>n</code> in this list. - * @throws Predef.NoSuchElementException if the list is too short. - */ - def apply(n: Int): A = drop(n).head - - /** Returns the list resulting from applying the given function <code>f</code> to each - * element of this list. - * - * @param f function to apply to each element. - * @return <code>[f(a0), ..., f(an)]</code> if this list is <code>[a0, ..., an]</code>. - */ - final override def map[B](f: A => B): List[B] = { - val b = new ListBuffer[B] - var these = this - while (!these.isEmpty) { - b += f(these.head) - these = these.tail - } - b.toList - } - - /** Apply a function to all the elements of the list, and return the - * reversed list of results. This is equivalent to a call to <code>map</code> - * followed by a call to <code>reverse</code>, but more efficient. - * - * @param f the function to apply to each elements. - * @return the reversed list of results. - */ - def reverseMap[B](f: A => B): List[B] = { - @tailrec - def loop(l: List[A], res: List[B]): List[B] = l match { - case Nil => res - case head :: tail => loop(tail, f(head) :: res) - } - loop(this, Nil) - } - - /** Apply the given function <code>f</code> to each element of this list - * (while respecting the order of the elements). - * - * @param f the treatment to apply to each element. - */ - final override def foreach(f: A => Unit) { - var these = this - while (!these.isEmpty) { - f(these.head) - these = these.tail - } - } - - /** Returns all the elements of this list that satisfy the - * predicate <code>p</code>. The order of the elements is preserved. - * It is guarenteed that the receiver list itself is returned iff all its - * elements satisfy the predicate `p'. Hence the following equality is valid: - * - * (xs filter p) eq xs == xs forall p - * - * @param p the predicate used to filter the list. - * @return the elements of this list satisfying <code>p</code>. - */ - final override def filter(p: A => Boolean): List[A] = { - // return same list if all elements satisfy p - var these = this - while (!these.isEmpty && p(these.head)) { - these = these.tail - } - if (these.isEmpty) this - else { - val b = new ListBuffer[A] - var these1 = this - while (these1 ne these) { - b += these1.head - these1 = these1.tail - } - - these = these.tail // prevent the second evaluation of the predicate - // on the element on which it first failed - while (!these.isEmpty) { - if (p(these.head)) b += these.head - these = these.tail - } - b.toList - } - } - -// final def filterMap[B](f: PartialFunction[A, B]): List[B] = -// this filter f.isDefinedAt map f - - /** Removes all elements of the list which satisfy the predicate - * <code>p</code>. This is like <code>filter</code> with the - * predicate inversed. - * - * @param p the predicate to use to test elements - * @return the list without all elements which satisfy <code>p</code> - */ - def remove(p: A => Boolean): List[A] = filter (x => !p(x)) - - /** Partition the list in two sub-lists according to a predicate. - * - * @param p the predicate on which to partition - * @return a pair of lists: the list of all elements which satisfy - * <code>p</code> and the list of all elements which do not. - * The relative order of the elements in the sub-lists is the - * same as in the original list. - */ - override def partition(p: A => Boolean): (List[A], List[A]) = { - val btrue = new ListBuffer[A] - val bfalse = new ListBuffer[A] - var these = this - while (!these.isEmpty) { - (if (p(these.head)) btrue else bfalse) += these.head - these = these.tail - } - (btrue.toList, bfalse.toList) - } - - /** <p> - * Sort the list according to the comparison function - * <code><(e1: a, e2: a) => Boolean</code>, - * which should be true iff <code>e1</code> is smaller than - * <code>e2</code>. - * </p> - * - * @param lt the comparison function - * @return a list sorted according to the comparison function - * <code><(e1: a, e2: a) => Boolean</code>. - * @ex <pre> - * List("Steve", "Tom", "John", "Bob") - * .sort((e1, e2) => (e1 compareTo e2) < 0) = - * List("Bob", "John", "Steve", "Tom")</pre> - */ - def sort(lt : (A,A) => Boolean): List[A] = { - /** Merge two already-sorted lists */ - def merge(l1: List[A], l2: List[A]): List[A] = { - val res = new ListBuffer[A] - var left1 = l1 - var left2 = l2 - - while (!left1.isEmpty && !left2.isEmpty) { - if(lt(left1.head, left2.head)) { - res += left1.head - left1 = left1.tail - } else { - res += left2.head - left2 = left2.tail - } - } - - res ++= left1 - res ++= left2 - - res.toList - } - - /** Split a list into two lists of about the same size */ - def split(lst: List[A]) = { - val res1 = new ListBuffer[A] - val res2 = new ListBuffer[A] - var left = lst - - while (!left.isEmpty) { - res1 += left.head - left = left.tail - if (!left.isEmpty) { - res2 += left.head - left = left.tail - } - } - - (res1.toList, res2.toList) - } - - - /** Merge-sort the specified list */ - def ms(lst: List[A]): List[A] = - lst match { - case Nil => lst - case x :: Nil => lst - case x :: y :: Nil => - if (lt(x,y)) - lst - else - y :: x :: Nil - - case lst => - val (l1, l2) = split(lst) - val l1s = ms(l1) - val l2s = ms(l2) - merge(l1s, l2s) - } - - ms(this) - } - - - /** Count the number of elements in the list which satisfy a predicate. - * - * @param p the predicate for which to count - * @return the number of elements satisfying the predicate <code>p</code>. - */ - def count(p: A => Boolean): Int = { - var cnt = 0 - var these = this - while (!these.isEmpty) { - if (p(these.head)) cnt += 1 - these = these.tail - } - cnt - } - - /** Tests if the predicate <code>p</code> is satisfied by all elements - * in this list. - * - * @param p the test predicate. - * @return <code>true</code> iff all elements of this list satisfy the - * predicate <code>p</code>. - */ - override def forall(p: A => Boolean): Boolean = { - var these = this - while (!these.isEmpty) { - if (!p(these.head)) return false - these = these.tail - } - true - } - - /** Tests the existence in this list of an element that satisfies the - * predicate <code>p</code>. - * - * @param p the test predicate. - * @return <code>true</code> iff there exists an element in this list that - * satisfies the predicate <code>p</code>. - */ - override def exists(p: A => Boolean): Boolean = { - var these = this - while (!these.isEmpty) { - if (p(these.head)) return true - these = these.tail - } - false - } - - /** Find and return the first element of the list satisfying a - * predicate, if any. - * - * @param p the predicate - * @return the first element in the list satisfying <code>p</code>, - * or <code>None</code> if none exists. - */ - override def find(p: A => Boolean): Option[A] = { - var these = this - while (!these.isEmpty) { - if (p(these.head)) return Some(these.head) - these = these.tail - } - None - } - - /** Combines the elements of this list together using the binary - * function <code>f</code>, from left to right, and starting with - * the value <code>z</code>. - * - * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...), - * a<sub>n</sub>)</code> if the list is - * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>. - */ - override def foldLeft[B](z: B)(f: (B, A) => B): B = { - var acc = z - var these = this - while (!these.isEmpty) { - acc = f(acc, these.head) - these = these.tail - } - acc - } - - /** Combines the elements of this list together using the binary - * function <code>f</code>, from right to left, and starting with - * the value <code>z</code>. - * - * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code> - * if the list is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>. - */ - override def foldRight[B](z: B)(f: (A, B) => B): B = this match { - case Nil => z - case x :: xs => f(x, xs.foldRight(z)(f)) - } - - /** Combines the elements of this list together using the binary - * operator <code>op</code>, from left to right - * @param op The operator to apply - * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code> - if the list has elements - * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>. - * @throws Predef.UnsupportedOperationException if the list is empty. - */ - override def reduceLeft[B >: A](f: (B, A) => B): B = this match { - case Nil => throw new UnsupportedOperationException("Nil.reduceLeft") - case x :: Nil => x - case x0 :: x1 :: xs => - var acc : B = f(x0, x1) - var these : List[A] = xs - while (!these.isEmpty) { - acc = f(acc, these.head) - these = these.tail - } - acc - } - - /** Combines the elements of this list together using the binary - * operator <code>op</code>, from right to left - * @param op The operator to apply - * - * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code> - * if the list has elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., - * a<sub>n</sub></code>. - * - * @throws Predef.UnsupportedOperationException if the list is empty. - */ - override def reduceRight[B >: A](f: (A, B) => B): B = this match { - case Nil => throw new UnsupportedOperationException("Nil.reduceRight") - case x :: Nil => x - case x :: xs => f(x, xs reduceRight f) - } - - /** Applies the given function <code>f</code> to each element of - * this list, then concatenates the results. - * - * @param f the function to apply on each element. - * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if - * this list is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>. - */ - final override def flatMap[B](f: A => Iterable[B]): List[B] = { - val b = new ListBuffer[B] - var these = this - while (!these.isEmpty) { - var those = f(these.head).elements - while (those.hasNext) { - b += those.next - } - these = these.tail - } - b.toList - } - - /** A list consisting of all elements of this list in reverse order. - */ - override def reverse: List[A] = { - var result: List[A] = Nil - var these = this - while (!these.isEmpty) { - result = these.head :: result - these = these.tail - } - result - } - - /** Returns a list formed from this list and the specified list - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * If one of the two lists is longer than the other, its remaining elements are ignored. - * - * @return <code>List((a<sub>0</sub>,b<sub>0</sub>), ..., - * (a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>))</code> when - * <code>List(a<sub>0</sub>, ..., a<sub>m</sub>) - * zip List(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked. - */ - def zip[B](that: List[B]): List[(A, B)] = { - val b = new ListBuffer[(A, B)] - var these = this - var those = that - while (!these.isEmpty && !those.isEmpty) { - b += ((these.head, those.head)) - these = these.tail - those = those.tail - } - b.toList - } - - /** Returns a list that pairs each element of this list - * with its index, counting from 0. - * - * @return the list <code>List((a<sub>0</sub>,0), (a<sub>1</sub>,1), ...)</code> - * where <code>a<sub>i</sub></code> are the elements of this list. - */ - def zipWithIndex: List[(A, Int)] = { - val b = new ListBuffer[(A, Int)] - var these = this - var idx = 0 - - while(!these.isEmpty) { - b += ((these.head, idx)) - these = these.tail - idx += 1 - } - - b.toList - } - - /** Returns a list formed from this list and the specified list - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * - * @param that list <code>that</code> may have a different length - * as the self list. - * @param thisElem element <code>thisElem</code> is used to fill up the - * resulting list if the self list is shorter than - * <code>that</code> - * @param thatElem element <code>thatElem</code> is used to fill up the - * resulting list if <code>that</code> is shorter than - * the self list - * @return <code>List((a<sub>0</sub>,b<sub>0</sub>), ..., - * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>), - * ..., {elem,b<sub>m</sub>})</code> - * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip - * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is - * invoked where <code>m > n</code>. - */ - def zipAll[B, C >: A, D >: B](that: List[B], thisElem: C, thatElem: D): List[(C, D)] = { - val b = new ListBuffer[(C, D)] - var these = this - var those = that - while (!these.isEmpty && !those.isEmpty) { - b += ((these.head, those.head)) - these = these.tail - those = those.tail - } - while (!these.isEmpty) { - b += ((these.head, thatElem)) - these = these.tail - } - while (!those.isEmpty) { - b += ((thisElem, those.head)) - those = those.tail - } - b.toList - } - - /** <p> - * Computes the multiset union of this list and the given list - * <code>that</code>. For example: - * </p><pre> - * <b>val</b> xs = List(1, 1, 2) - * <b>val</b> ys = List(1, 2, 2, 3) - * println(xs union ys) // prints "List(1, 1, 2, 1, 2, 2, 3)" - * println(ys union xs) // prints "List(1, 2, 2, 3, 1, 1, 2)" - * </pre> - * - * @param that the list of elements to add to the list. - * @return a list containing the elements of this - * list and those of the given list <code>that</code>. - */ - def union[B >: A](that: List[B]): List[B] = this ++ that - - /** <p> - * Computes the multiset intersection between this list and the - * given list <code>that</code>; the intersection contains <i>m</i> - * copies of an element contained in both lists, where <i>m</i> is - * the smaller of the number of times the element appears in this - * list or in <code>that</code>. For example: - * </p><pre> - * <b>val</b> xs = List(1, 1, 2) - * <b>val</b> ys = List(3, 2, 2, 1) - * println(xs intersect ys) // prints "List(1, 2)" - * println(ys intersect xs) // prints "List(2, 1)" - * </pre> - * - * @param that the list to intersect. - * @return the list of elements contained both in this list and - * in the given list <code>that</code>. - */ - def intersect[B >: A](that: List[B]): List[B] = { - val occ = new LinkedHashMap[B, Int] - that foreach (e => if (occ contains e) occ(e) += 1 else occ(e) = 1) - val buf = new ListBuffer[B] - for (e <- this if occ contains e) { - if (occ(e) > 0) { occ(e) -= 1; buf += e } - } - buf.toList - } - - /** <p> - * Computes the multiset difference between this list and the - * given list <code>that</code>. If an element appears more - * than once in both lists, the difference contains <i>m</i> copies - * of that element, where <i>m</i> is the difference between the - * number of times the element appears in this list and the number - * of times it appears in <code>that</code>. For example: - * </p><pre> - * <b>val</b> xs = List(1, 1, 2) - * <b>val</b> ys = List(1, 2, 2, 3) - * println(xs diff ys) // prints "List(1)" - * println(xs -- ys) // prints "List()" - * </pre> - * - * @param that the list of elements to remove from this list. - * @return the list of elements contained only in this list plus - * <i>m</i> copies of each element present in both lists, - * where <i>m</i> is defined as above. - */ - def diff[B >: A](that: List[B]): List[B] = { - val occ = new LinkedHashMap[B, Int] - that foreach (e => if (occ contains e) occ(e) += 1 else occ(e) = 1) - val buf = new ListBuffer[B] - for (e <- this) { - if (occ contains e) - if (occ(e) > 0) occ(e) -= 1 - else buf += e - else buf += e - } - buf.toList - } - - /** Computes the difference between this list and the given list - * <code>that</code>. - * - * @param that the list of elements to remove from this list. - * @return this list without the elements of the given list - * <code>that</code>. - */ - def -- [B >: A](that: List[B]): List[B] = { - val b = new ListBuffer[B] - var these = this - while (!these.isEmpty) { - if (!that.contains(these.head)) b += these.head - these = these.tail - } - b.toList - } - - /** Computes the difference between this list and the given object - * <code>x</code>. - * - * @param x the object to remove from this list. - * @return this list without the elements of the given object - * <code>x</code>. - */ - def - [B >: A](x: B): List[B] = { - val b = new ListBuffer[B] - var these = this - while (!these.isEmpty) { - if (these.head != x) b += these.head - these = these.tail - } - b.toList - } - - /** Concatenate the elements of this list. The elements of this list - * should be a <code>Iterables</code>. - * - * Note: The compiler might not be able to infer the type parameter, - * so it is recommended to provide an explicit type argument. - * - * Example: - * <code>List(List(1, 3), List(2)).flatten[Int]</code> - * returns - * <code>List(1, 3, 2)</code> - * - * @param f An implicit conversion to an <code>Iterable</code> instance. - * @return The concatenation of all elements of iterables in this list. - */ - def flatten[B](implicit f : A => Iterable[B]) : List[B] = { - val buf = new ListBuffer[B] - foreach(f(_).foreach(buf += _)) - buf.toList - } - - /** Removes redundant elements from the list. Uses the method <code>==</code> - * to decide if two elements are identical. - * - * @return the list without doubles. - */ - def removeDuplicates: List[A] = { - val b = new ListBuffer[A] - var these = this - while (!these.isEmpty) { - if (!these.tail.contains(these.head)) b += these.head - these = these.tail - } - b.toList - } - - override protected def stringPrefix = "List" - override def projection = toStream - override def toStream : Stream[A] = new Stream.Definite[A] { - override def force : List[A] = List.this - override def isEmpty = List.this.isEmpty - override def head = List.this.head - override def tail = List.this.tail.toStream - protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder = if (!isEmpty) { - var prefix0 = prefix - var buf1 = buf.append(prefix0).append(head) - prefix0 = ", " - var tail0 = tail - while (!tail0.isEmpty) { - buf1 = buf.append(prefix0).append(tail0.head) - tail0 = tail0.tail - } - buf1 - } else buf - } - -} - -/** The empty list. - * - * @author Martin Odersky - * @version 1.0, 15/07/2003 - */ -@SerialVersionUID(0 - 8256821097970055419L) -case object Nil extends List[Nothing] { - override def isEmpty = true - def head: Nothing = - throw new NoSuchElementException("head of empty list") - def tail: List[Nothing] = - throw new NoSuchElementException("tail of empty list") -} - -/** A non empty list characterized by a head and a tail. - * - * @author Martin Odersky - * @version 1.0, 15/07/2003 - */ -@SerialVersionUID(0L - 8476791151983527571L) -final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B] { - def head : B = hd - def tail : List[B] = tl - override def isEmpty: Boolean = false - - import java.io._ - - private def writeObject(out: ObjectOutputStream) { - var xs: List[B] = this - while (!xs.isEmpty) { out.writeObject(xs.head); xs = xs.tail } - out.writeObject(ListSerializeEnd) - } - - private def readObject(in: ObjectInputStream) { - hd = in.readObject.asInstanceOf[B] - assert(hd != ListSerializeEnd) - var current: ::[B] = this - while (true) in.readObject match { - case ListSerializeEnd => - current.tl = Nil - return - case a : Any => - val list : ::[B] = new ::(a.asInstanceOf[B], Nil) - current.tl = list - current = list - } - } -} - -/** Only used for list serialization */ -@SerialVersionUID(0L - 8476791151975527571L) -private[scala] case object ListSerializeEnd diff --git a/src/library/scala/Mutable.scala b/src/library/scala/Mutable.scala new file mode 100755 index 0000000000..2c596e2b81 --- /dev/null +++ b/src/library/scala/Mutable.scala @@ -0,0 +1,11 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala + +/** A marker trait for mutable datatructures such as mutable collections */ +trait Mutable diff --git a/src/library/scalax/Numeric.scala b/src/library/scala/Numeric.scala index 6e61851dc5..4f7e4749cf 100755 --- a/src/library/scalax/Numeric.scala +++ b/src/library/scala/Numeric.scala @@ -1,4 +1,4 @@ -package scalax +package scala object Numeric { implicit object IntIsIntegral extends Integral[Int] { diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 8b4c00bf9c..93c9e29040 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -61,6 +61,10 @@ object Predef { // miscelleaneous ----------------------------------------------------- + private val P = scala.`package` // to force scala package object to be seen. + private val L = scala.collection.immutable.List // to force Nil, :: to be seen. + private val S = scala.collection.mutable.StringBuilder // to force StringBuilder to be seen. + val $scope = scala.xml.TopScope type Function[-A, +B] = Function1[A, B] @@ -189,7 +193,6 @@ object Predef { implicit def unitWrapper(x: Boolean) = new runtime.RichUnit implicit def stringWrapper(x: String) = new runtime.RichString(x) - implicit def stringBuilderWrapper(x : StringBuilder): runtime.RichStringBuilder = new runtime.RichStringBuilder(x) implicit def any2stringadd(x: Any) = new runtime.StringAdd(x) @@ -331,12 +334,12 @@ object Predef { implicit def boolean2Boolean(x: Boolean) = java.lang.Boolean.valueOf(x) /** any array projection can be automatically converted into an array */ - implicit def forceArrayProjection[A](x: Array.Projection[A]): Array[A] = x.force + //implicit def forceArrayProjection[A](x: Array.Projection[A]): Array[A] = x.force !!! re-enable? /** any random access character seq (including rich string can be converted into a string */ - implicit def forceRandomAccessCharSeq(x: runtime.RichString): String = x.mkString - implicit def lazyStreamToConsable[A](xs: => Stream[A]) = new runtime.StreamCons(xs) + //implicit def forceRandomAccessCharSeq(x: runtime.RichString): String = x.mkString + //implicit def lazyStreamToConsable[A](xs: => Stream[A]) = new runtime.StreamCons(xs) - implicit def seqToCharSequence(xs: RandomAccessSeq[Char]): CharSequence = new CharSequence { + implicit def seqToCharSequence(xs: collection.Vector[Char]): CharSequence = new CharSequence { def length: Int = xs.length def charAt(index: Int): Char = xs(index) def subSequence(start: Int, end: Int): CharSequence = seqToCharSequence(xs.slice(start, end)) diff --git a/src/library/scala/RandomAccessSeq.scala b/src/library/scala/RandomAccessSeq.scala deleted file mode 100644 index 2c5c637a6f..0000000000 --- a/src/library/scala/RandomAccessSeq.scala +++ /dev/null @@ -1,245 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala - -import collection.mutable.ArrayBuffer - -object RandomAccessSeq { - - /** Create read only sequence of specified elements */ - def apply[A](xs: A*): RandomAccessSeq[A] = - if (xs.isEmpty) empty - else { - val buffer = new ArrayBuffer[A] - xs copyToBuffer buffer - buffer.readOnly - } - - /** The empty sequence */ - val empty : RandomAccessSeq[Nothing] = new RandomAccessSeq.Projection[Nothing] { - def length = 0 - def apply(i: Int): Nothing = throw new NoSuchElementException("empty sequence") - override def elements = Iterator.empty - override def projection = this - override def force = this - } - - trait Projection[+A] extends Seq.Projection[A] with RandomAccessSeq[A] { - override def projection = this - override def force : RandomAccessSeq[A] = toArray - protected class MapProjection[B](f : A => B) extends super.MapProjection(f) with Projection[B] - override def map[B](f: A => B) : Projection[B] = new MapProjection[B](f) - override def append[B >: A](that: => Iterable[B]): Projection[B] = { - val that0 : Seq[B] = that match { - case that : Seq.Projection[b] => that - case that : Seq[b] => that - case that => that.toList - } - new Projection[B] { - def length = Projection.this.length + that0.length - def apply(idx : Int) = - if (idx < Projection.this.length) Projection.this(idx) - else that0(idx - Projection.this.length) - } - } - } - private[scala] trait Slice[+A] extends Projection[A] { - protected def from : Int - protected def until : Int - protected def underlying : RandomAccessSeq[A] - def length = { - val length0 = underlying.length - if (from >= until || from >= length0) 0 - else (if (until >= length0) length0 else until) - (if (from < 0) 0 else from) - } - def apply(idx : Int) = if (idx < 0 || idx >= length) throw new Predef.IndexOutOfBoundsException - else underlying.apply((if (from < 0) 0 else from) + idx) - override def slice(from0 : Int, until0 : Int) = { - val from = if (this.from < 0) 0 else this.from - underlying.slice(from + from0, from + until0) - } - } - private[scala] trait Patch[+A] extends Projection[A] { - protected def original : RandomAccessSeq[A] - protected def patch : RandomAccessSeq[A] - protected def from : Int - protected def replaced : Int - def length = original.length + patch.length - replaced - def apply(idx : Int) = - if (idx < from) original.apply(idx) - else if (idx < from + patch.length) patch.apply(idx - from) - else original.apply(idx - patch.length + replaced) - override def stringPrefix = "patch" - } - - /** A random access sequence that supports update (e.g., an array) */ - trait Mutable[A] extends RandomAccessSeq[A] { - /** <p> - * Update the element at given index. - * </p> - * <p> - * Indices start a <code>0</code>; <code>xs.apply(0)</code> is the first - * element of mutable sequence <code>xs</code>. - * </p> - * <p> - * Note the indexing syntax <code>xs(i) = x</code> is a shorthand - * for <code>xs.update(i, x)</code>. - * </p> - * - * @param i the index - * @param x the value to be written at index <code>i</code> - * @throws ArrayIndexOutOfBoundsException if <code>i < 0</code> or - * <code>length <= i</code> - */ - def update(idx : Int, what : A) : Unit - override def projection : MutableProjection[A] = new MutableProjection[A] { - override def force : Mutable[A] = Mutable.this - def update(idx : Int, what : A) : Unit = Mutable.this.update(idx, what) - def length = Mutable.this.length - def apply(idx : Int) = Mutable.this.apply(idx) - } - def readOnly : RandomAccessSeq[A] = new RandomAccessSeq[A] { - def length = Mutable.this.length - def apply(idx : Int) = Mutable.this.apply(idx) - override def stringPrefix = Mutable.this.stringPrefix + "RO" - } - override def drop( from: Int): MutableProjection[A] = slice(from, length) - override def take(until: Int): MutableProjection[A] = slice(0, until) - override def slice(from0: Int, until0: Int) : MutableProjection[A] = new MutableSlice[A] { - def from = from0 - def until = until0 - def underlying = Mutable.this - } - override def reverse : MutableProjection[A] = new MutableProjection[A] { - def update(idx: Int, what: A) { Mutable.this.update(length - idx - 1, what) } - def length = Mutable.this.length - def apply(idx: Int) = Mutable.this.apply(length - idx - 1) - override def stringPrefix = Mutable.this.stringPrefix + "R" - override def reverse: MutableProjection[A] = Mutable.this.projection - } - } - trait MutableProjection[A] extends Projection[A] with Mutable[A] { - override def force : Mutable[A] = toArray - override def projection : MutableProjection[A] = this - } - private[scala] trait MutableSlice[A] extends MutableProjection[A] with Slice[A] { - protected def underlying : Mutable[A] - override def slice(from0 : Int, until0 : Int) = { - val from = (if (this.from < 0) 0 else this.from) - underlying.slice(from + from0, from + until0) - } - override def update(idx : Int, what : A) : Unit = { - val from = (if (this.from < 0) 0 else this.from) - if (idx < 0 || idx >= length) throw new Predef.IndexOutOfBoundsException - else underlying.update(from + idx, what) - } - } -} - -/** Sequences that support O(1) element access and O(1) length computation. - * @author Sean McDirmid - */ -trait RandomAccessSeq[+A] extends Seq[A] { - override def projection : RandomAccessSeq.Projection[A] = new RandomAccessSeq.Projection[A] { - def length = RandomAccessSeq.this.length - def apply(idx : Int) = RandomAccessSeq.this.apply(idx) - override def elements = RandomAccessSeq.this.elements - override def stringPrefix = RandomAccessSeq.this.stringPrefix + "P" - } - override def elements : Iterator[A] = new BufferedIterator.Advanced[A] { - var idx = 0 - override def peekList(sz : Int) = new RandomAccessSeq[A] { - override def length = RandomAccessSeq.this.length - idx - override def apply(jdx : Int) = RandomAccessSeq.this.apply(jdx + idx) - } - override def hasNext = idx < RandomAccessSeq.this.length - def next = { - if (!hasNext) throw new Predef.NoSuchElementException - val ret = RandomAccessSeq.this.apply(idx) - idx += 1 - ret - } - } - override def drop( from: Int): RandomAccessSeq[A] = slice(from, length) - override def take(until: Int): RandomAccessSeq[A] = slice(0, until) - override def slice(from0 : Int, until0 : Int) : RandomAccessSeq[A] = new RandomAccessSeq.Slice[A] { - def from = from0 - def until = until0 - def underlying = RandomAccessSeq.this - } - override def reverse : Seq[A] = new RandomAccessSeq.Projection[A] { - def length = RandomAccessSeq.this.length - def apply(idx : Int) = RandomAccessSeq.this.apply(length - idx - 1) - override def stringPrefix = RandomAccessSeq.this.stringPrefix + "R" - override def reverse : RandomAccessSeq.Projection[A] = RandomAccessSeq.this.projection - } - - /** Partitions this random access sequence in two random access - * sequences according to a predicate. - * - * @param p the predicate on which to partition - * @return a pair of random access sequences: the sequence of all elements - * that satisfy the predicate <code>p</code> and the sequence of - * all elements that do not. - * The relative order of the elements in the resulting sequences - * is the same as in the original sequence. - */ - override def partition(p: A => Boolean): (RandomAccessSeq[A], RandomAccessSeq[A]) = { - val matched = new ArrayBuffer[A] - val failed = new ArrayBuffer[A] - val elems = elements - while (elems.hasNext) { val x = elems.next; if (p(x)) matched += x else failed += x } - (matched, failed) - } - - /** insert segment <code>patch</code> into this sequence at <code>from</code> - * replacing <code>replaced</code> elements. The result is a projection. - */ - def patch[B >: A](from0: Int, patch0: RandomAccessSeq[B], replaced0: Int): RandomAccessSeq.Projection[B] = new RandomAccessSeq.Patch[B] { - override def original = RandomAccessSeq.this - override def from = from0 - override def patch = patch0 - override def replaced = replaced0 - override def stringPrefix = RandomAccessSeq.this.stringPrefix + "P" - } - - override def ++[B >: A](that: Iterable[B]): RandomAccessSeq[B] = that match { - case that: RandomAccessSeq[b] => - val ret = new Array[B](length + that.length) - copyToArray(ret, 0) - (that : RandomAccessSeq[B]).copyToArray(ret, length) - ret - case that => - val buf = new scala.collection.mutable.ArrayBuffer[B] - this copyToBuffer buf - that copyToBuffer buf - buf.readOnly - } - - override def toStream : Stream[A] = new Stream.Definite[A] { - override def isEmpty = RandomAccessSeq.this.isEmpty - override def head = RandomAccessSeq.this.apply(0) - override def tail = RandomAccessSeq.this.drop(1).toStream - protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder = { - var prefix0 = prefix - var buf0 = buf - elements.foreach{e => - buf0 = buf0.append(prefix0).append(e) - prefix0 = ", " - } - buf0 - } - } - - /** will return false if index is out of bounds */ - final def safeIs(idx : Int, a : Any) = if (idx >= 0 && idx < length) this(idx) == a else false - -} diff --git a/src/library/scala/RandomAccessSeqProxy.scala b/src/library/scala/RandomAccessSeqProxy.scala deleted file mode 100644 index 2db37cd5c3..0000000000 --- a/src/library/scala/RandomAccessSeqProxy.scala +++ /dev/null @@ -1,37 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - -/** This class implements a proxy for random access sequences. It forwards - * all calls to a different sequence object. - * - * @author Stepan Koltsov - * @version 1.0, 27/06/2008 - */ -trait RandomAccessSeqProxy[+A] extends RandomAccessSeq[A] with SeqProxy[A] { - override def self: RandomAccessSeq[A] - - override def projection = self.projection - - override def drop(from: Int): RandomAccessSeq[A] = self.drop(from) - override def take(until: Int): RandomAccessSeq[A] = self.take(until) - override def slice(from: Int, until: Int) : RandomAccessSeq[A] = self.slice(from, until) - override def reverse = self.reverse - override def partition(p: A => Boolean): (RandomAccessSeq[A], RandomAccessSeq[A]) = - self.partition(p) - override def patch[B >: A](from0: Int, patch0: RandomAccessSeq[B], replaced0: Int) = - self.patch(from0, patch0, replaced0) - override def ++[B >: A](that: Iterable[B]): RandomAccessSeq[B] = self ++ that - override def toStream: Stream[A] = self.toStream -} - -// vim: set ts=2 sw=2 et: diff --git a/src/library/scala/Range.scala b/src/library/scala/Range.scala index fcf8c809ad..c78f0718f3 100644 --- a/src/library/scala/Range.scala +++ b/src/library/scala/Range.scala @@ -11,7 +11,8 @@ package scala -import Predef._ +import collection.immutable.Vector +import collection.generic.VectorView /** <p> * The <code>Range</code> class represents integer values in range @@ -24,11 +25,13 @@ import Predef._ * println(r2.length) // = 5 * </pre> * - * @author Stephane Micheloud - * @version 1.0, 01/05/2007 + * @author Martin Odersky + * @version 2.8 */ -class Range(val start: Int, val end: Int, val step: Int) extends RandomAccessSeq.Projection[Int] { - if (step == 0) throw new Predef.IllegalArgumentException +class Range(val start: Int, val end: Int, val step: Int) extends VectorView[Int, Vector[Int]] { + require(step != 0) + + protected def underlying = Vector.empty[Int] /** Create a new range with the start and end values of this range and * a new <code>step</code>. @@ -36,19 +39,14 @@ class Range(val start: Int, val end: Int, val step: Int) extends RandomAccessSeq def by(step: Int): Range = new Range(start, end, step) override def foreach(f: Int => Unit) { + var i = start if (step > 0) { - var i = this.start - val until = if (inInterval(end)) end + 1 else end - - while (i < until) { + while (i < end) { f(i) i += step } } else { - var i = this.start - val until = if (inInterval(end)) end - 1 else end - - while (i > until) { + while (i > end) { f(i) i += step } @@ -56,54 +54,33 @@ class Range(val start: Int, val end: Int, val step: Int) extends RandomAccessSeq } lazy val length: Int = { - if (start < end && this.step < 0) 0 - else if (start > end && this.step > 0) 0 - else { - val base = if (start < end) end - start - else start - end - assert(base >= 0) - val step = if (this.step < 0) -this.step else this.step - assert(step >= 0) - base / step + last(base, step) - } + def plen(start: Int, end: Int, step: Int) = + if (end <= start) 0 else (end - start - 1) / step + 1 + if (step > 0) plen(start, end, step) + else plen(end, start, -step) } - protected def last(base: Int, step: Int): Int = - if (base % step != 0) 1 else 0 - def apply(idx: Int): Int = { - if (idx < 0 || idx >= length) throw new Predef.IndexOutOfBoundsException - start + (step * idx) - } - - /** a <code>Seq.contains</code>, not a <code>Iterator.contains</code>! */ - def contains(x: Int): Boolean = { - inInterval(x) && (((x - start) % step) == 0) + if (idx < 0 || idx >= length) throw new IndexOutOfBoundsException(idx.toString) + start + idx * step } - /** Is the argument inside the interval defined by `start' and `end'? - * Returns true if `x' is inside [start, end). - */ - protected def inInterval(x: Int): Boolean = - if (step > 0) - (x >= start && x < end) - else - (x <= start && x > end) + def contains(x: Int): Boolean = + if (step > 0) start <= x && x < end + else start >= x && x > end - def inclusive = new Range.Inclusive(start,end,step) + def inclusive = Range.inclusive(start, end, step) } - object Range { - class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) { - override def apply(idx: Int): Int = super.apply(idx) - override protected def last(base: Int, step: Int): Int = 1 - override def by(step: Int): Range = new Inclusive(start, end, step) - - /** Returns true if x is inside the interval [start, end]. */ - override protected def inInterval(x: Int) = - if (step > 0) - (x >= start && x <= end) - else - (x <= start && x >= end) + /** @deprecated use Range.inclusive instead */ + class Inclusive(start: Int, end0: Int, step: Int) + extends Range(start, if (step > 0) end0 + 1 else end0 - 1, step) { self => + override def by(step: Int): Range = new Inclusive(start, end0, step) } + + def apply(start: Int, end: Int, step: Int) = + new Range(start, end, step) + + def inclusive(start: Int, end: Int, step: Int): Range = + new Range.Inclusive(start, end, step) } diff --git a/src/library/scala/Seq.scala b/src/library/scala/Seq.scala deleted file mode 100644 index 656d3b6fab..0000000000 --- a/src/library/scala/Seq.scala +++ /dev/null @@ -1,515 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - -import Predef._ -import collection.mutable.ArrayBuffer - -object Seq { - - /** The empty sequence */ - val empty : Seq[Nothing] = RandomAccessSeq.empty - - /** This method is called in a pattern match { case Seq(...) => }. - * - * @param x the selector value - * @return sequence wrapped in an option, if this is a Seq, otherwise none - */ - def unapplySeq[A](x: Seq[A]): Some[Seq[A]] = Some(x) - - /** Create read only sequence of specified elements */ - def apply[A](xs: A*): Seq[A] = RandomAccessSeq(xs: _*) - - case class singleton[A](value: A) extends RandomAccessSeq[A] { - override def length = 1 - override def isDefinedAt(idx: Int): Boolean = idx == 0 - override def apply(idx: Int) = idx match { - case 0 => value - case _ => throw new Predef.IndexOutOfBoundsException - } - } - - /** Builds a singleton sequence. - * - * @deprecated use <code>singleton</code> instead. - */ - @deprecated def single[A](x: A) = singleton(x) - - trait Projection[+A] extends Seq[A] with Iterable.Projection[A] { - override def projection = this - override def force : Seq[A] = toList - - override def map[B](f: A => B) : Projection[B] = new MapProjection(f) - protected class MapProjection[B](f : A => B) extends Projection[B] { - def length = Projection.this.length - def elements = Projection.this.elements.map(f) - def apply(idx : Int) = f(Projection.this.apply(idx)) - override def stringPrefix = Projection.this.stringPrefix + "M" - } - override def flatMap[B](f: A => Iterable[B]): Projection[B] = new Projection[B] { - override def stringPrefix = Projection.this.stringPrefix + "G" - def elements = Projection.this.elements.flatMap(a => f(a).elements) - def length = { - var sz = 0 - Projection.this.foreach(a => sz = sz + f(a).asInstanceOf[Collection[B]].size) - sz - } - def apply(idx : Int) : B = { - var jdx = 0 - Projection.this.foreach(a => { - val i = f(a) - val length = i.asInstanceOf[Collection[B]].size - if (idx < jdx + length) { - val j = i.elements - while (jdx < idx) { - j.next; jdx += 1 - } - return j.next - } else jdx += length - }) - throw new IndexOutOfBoundsException - } - } - override def append[B >: A](that: => Iterable[B]): Projection[B] = that match { - case that: Seq[b] => new Projection[B] { - def length = Projection.this.length + that.length - def elements : Iterator[B] = Projection.this.elements ++ (that.elements:Iterator[B]) - def apply(idx : Int) = - if (idx < Projection.this.length) Projection.this(idx) - else that(idx - Projection.this.length) - } - case that => - (this ++ that).projection // sucks but no other option. - } - - protected abstract class ComputeSize[B] extends Projection[B] { - def apply(idx: Int): B = { - var sz = 0 - val i = elements - while (i.hasNext) { - val ret = i.next - if (sz == idx) return ret - sz += 1 - } - throw new Predef.IndexOutOfBoundsException - } - override def length: Int = { - val i = elements - var sz = 0 - while (i.hasNext) { - sz += 1 - i.next - } - sz - } - } - override def takeWhile(p: A => Boolean): Projection[A] = new ComputeSize[A] { - override def stringPrefix = Projection.this.stringPrefix + "TW" - override def elements = Projection.this.elements.takeWhile(p) - } - override def filter(p : A => Boolean) : Projection[A] = new ComputeSize[A] { - override def stringPrefix = Projection.this.stringPrefix + "F" - override def elements = Projection.this.elements.filter(p) - } - } -} - - -/** Class <code>Seq[A]</code> represents finite sequences of elements - * of type <code>A</code>. - * - * @author Martin Odersky - * @author Matthias Zenger - * @version 1.0, 16/07/2003 - */ -trait Seq[+A] extends AnyRef with PartialFunction[Int, A] with Collection[A] { - - /** Returns the length of the sequence. - * - * @return the sequence length. - */ - def length: Int - - /** Result of comparing <code>length</code> with operand <code>l</code>. - * returns <code>x</code> where - * <code>x < 0</code> iff <code>this.length < l</code> - * <code>x == 0</code> iff <code>this.length == l</code> - * <code>x > 0</code> iff <code>this.length > that</code>. - * - * This method is used by matching streams against right-ignoring (...,_*) patterns. - * Lazy sequences should override this method if length forces evaluation of the stream. - */ - def lengthCompare(l: Int): Int = length - l - - /** should always be <code>length</code> */ - def size = length - - /** Returns true if length == 0 - */ - override def isEmpty: Boolean = { length == 0 } - - /** Appends two iterable objects. - * - * @return the new iterable object - * @deprecated use <code>++</code> instead - */ - @deprecated - override def concat [B >: A](that: Iterable[B]): Seq[B] = { - val buf = new ArrayBuffer[B] - this copyToBuffer buf - that copyToBuffer buf - buf.readOnly - } - - /** Returns the last element of this list. - * - * @return the last element of the list. - * @throws Predef.NoSuchElementException if the list is empty. - */ - def last: A = length match { - case 0 => throw new Predef.NoSuchElementException - case n => this(n - 1) - } - - /** Returns as an option the last element of this list or - * <code>None</code> if list is empty. - * - * @return the last element as an option. - */ - def lastOption: Option[A] = length match { - case 0 => None - case n => Some(this(n-1)) - } - - /** Returns the first element of this list. - * - * @return the first element of the list. - * @throws Predef.UnsupportedOperationException if the list is empty. - */ - def first: A = - if (isEmpty) throw new Predef.NoSuchElementException - else this(0) - - /** Returns as an option the first element of this list or - * <code>None</code> if list is empty. - * - * @return the first element as an option. - */ - def firstOption: Option[A] = if (isEmpty) None else Some(apply(0)) - - @deprecated - def headOption: Option[A] = firstOption - - /** Appends two iterable objects. - */ - override def ++ [B >: A](that: Iterable[B]): Seq[B] = { - val buf = new ArrayBuffer[B] - this copyToBuffer buf - that copyToBuffer buf - buf.readOnly - } - - /** Is this partial function defined for the index <code>x</code>? - * - * @param x .. - * @return <code>true</code>, iff <code>x</code> is a legal sequence index. - */ - def isDefinedAt(x: Int): Boolean = (x >= 0) && (x < length) - - /** Returns the index of the last occurence of the specified element - * in this sequence, or -1 if the sequence does not contain this element. - * - * @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. - */ - def lastIndexOf[B >: A](elem: B): Int = { - var i = length - var found = false - while (!found && (i > 0)) { - i -= 1 - if (this(i) == elem) found = true - } - if (found) i else -1 - } - - /** Returns index of the first element satisying a predicate, or -1. - * - * @note may not terminate for infinite-sized collections. - * @param p the predicate - * @return the index of the first element satisfying <code>p</code>, - * or -1 if such an element does not exist - */ - override def findIndexOf(p: A => Boolean): Int = - elements.findIndexOf(p) - - /** Returns the index of the first occurence of the specified - * object in this iterable object. - * - * @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. - */ - override def indexOf[B >: A](elem: B): Int = - elements.indexOf(elem) - - /** Returns the sequence resulting from applying the given function - * <code>f</code> to each element of this sequence. - * - * @param f function to apply to each element. - * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> if this - * sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. - */ - override def map[B](f: A => B): Seq[B] = { - // todo: malformed scala signature suing build when replaced by - // super.map(f).asInstanceOf[Seq[B2]] - val buf = new ArrayBuffer[B] - val elems = elements - while (elems.hasNext) buf += f(elems.next) - buf.readOnly - } - - /** Applies the given function <code>f</code> to each element of - * this sequence, then concatenates the results. - * - * @param f the function to apply on each element. - * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if - * this sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. - */ - override def flatMap[B](f: A => Iterable[B]): Seq[B] = { - val buf = new ArrayBuffer[B] - val elems = elements - while (elems.hasNext) f(elems.next) copyToBuffer buf - buf.readOnly - } - - /** Returns all the elements of this sequence that satisfy the - * predicate <code>p</code>. The order of the elements is preserved. - * - * @param p the predicate used to filter the list. - * @return the elements of this list satisfying <code>p</code>. - */ - override def filter(p: A => Boolean): Seq[A] = - super.filter(p).asInstanceOf[Seq[A]] - - /** Returns a sequence consisting only over the first <code>n</code> - * elements of this sequence, or else the whole sequence, if it has less - * than <code>n</code> elements. (non-strict) - * - * @param n the number of elements to take - * @return a possibly projected sequence - */ - override def take(n: Int): Seq[A] = { - var m = 0 - val result = new scala.collection.mutable.ListBuffer[A] - val i = elements - while (m < n && i.hasNext) { - result += i.next; m += 1 - } - result.toList - } - - - /** Returns this sequence without its <code>n</code> first elements - * If this sequence has less than <code>n</code> elements, the empty - * sequence is returned. (non-strict) - * - * @param n the number of elements to drop - * @return the new sequence - */ - override def drop(n: Int): Seq[A] = { - import scala.collection.mutable.ListBuffer - var m = 0 - val result = new ListBuffer[A] - val i = elements - while (m < n && i.hasNext) { - i.next; m += 1 - } - while (i.hasNext) result += i.next - result.toList - } - - /** A sub-sequence starting at index <code>from</code> - * and ending (non-inclusive) at index <code>until</code> (non-strict) - * - * @param from The index of the first element of the slice - * @param until The index of the element following the slice - * @throws IndexOutOfBoundsException if <code>from < 0</code> - * or <code>length < from + len<code> - */ - def slice(from: Int, until: Int): Seq[A] = drop(from).take(until - from) - - /** A sub-sequence starting at index <code>from</code> - * and extending up to the length of the current sequence (non-strict) - * - * @param from The index of the first element of the slice - * @throws IndexOutOfBoundsException if <code>from < 0</code> - * @deprecated Use <code>drop(n: Int): Seq[A]</code> instead. - */ - @deprecated def slice(from: Int): Seq[A] = slice(from, length) - - /** Returns the longest prefix of this sequence whose elements satisfy - * the predicate <code>p</code>. - * - * @param p the test predicate. - * @return the longest prefix of this sequence whose elements satisfy - * the predicate <code>p</code>. - */ - override def takeWhile(p: A => Boolean): Seq[A] = - super.takeWhile(p).asInstanceOf[Seq[A]] - - /** Returns the longest suffix of this sequence whose first element - * does not satisfy the predicate <code>p</code>. - * - * @param p the test predicate. - * @return the longest suffix of the sequence whose first element - * does not satisfy the predicate <code>p</code>. - */ - override def dropWhile(p: A => Boolean): Seq[A] = - super.dropWhile(p).asInstanceOf[Seq[A]] - - /** A sequence consisting of all elements of this sequence in reverse order. - */ - def reverse: Seq[A] = { - var result: List[A] = Nil - val elems = elements - while (elems.hasNext) result = elems.next :: result - result - } - - /** Tests if the given value <code>elem</code> is a member of this - * sequence. - * - * @param elem element whose membership has to be tested. - * @return <code>true</code> iff there is an element of this sequence - * which is equal (w.r.t. <code>==</code>) to <code>elem</code>. - */ - def contains(elem: Any): Boolean = exists (_ == elem) - - /** Returns a subsequence starting from index <code>from</code> - * consisting of <code>len</code> elements. - * - * @deprecated use <code>slice</code> instead - */ - @deprecated - def subseq(from: Int, end: Int): Seq[A] = slice(from, end - from) - - /** Converts this sequence to a fresh Array with <code>length</code> elements. - */ - override def toArray[B >: A]: Array[B] = { - val result = new Array[B](length) - copyToArray(result, 0) - result - } - - /** - * Overridden for efficiency. - * - * @return the sequence itself - */ - override def toSeq: Seq[A] = this - - override def projection: Seq.Projection[A] = new Seq.Projection[A] { - override def force: Seq[A] = Seq.this - def elements = Seq.this.elements - def length = Seq.this.length - def apply(idx: Int) = Seq.this.apply(idx) - override def stringPrefix = Seq.this.stringPrefix + "P" - } - - def equalsWith[B](that: Seq[B])(f: (A,B) => Boolean): Boolean = - if (size != that.size) false - else { - val i = elements - val j = that.elements - while (i.hasNext) if (!f(i.next, j.next)) return false - true - } - - /** - * Checks whether the argument sequence is contained at the - * specified index within the receiver object. - * - * If the both the receiver object, <code>this</code> and - * the argument, <code>that</code> are infinite sequences - * this method may not terminate. - * - * @return true if <code>that</code> is contained in - * <code>this</code>, at the specified index, otherwise false - * - * @see String.startsWith - */ - def startsWith[B](that: Seq[B], offset: Int): Boolean = { - val i = elements.drop(offset) - val j = that.elements - var result = true - while (j.hasNext && i.hasNext && result) - result = i.next == j.next - result && !j.hasNext - } - - /** - * Check whether the receiver object starts with the argument sequence. - * - * @return true if <code>that</code> is a prefix of <code>this</code>, - * otherwise false - * - * @see Seq.startsWith - */ - def startsWith[B](that: Seq[B]): Boolean = startsWith(that, 0) - - - /** @return true if this sequence end with that sequence - * @see String.endsWith - */ - def endsWith[B](that: Seq[B]): Boolean = - drop(length - that.length).sameElements(that) - - /** - * Searches for the argument sequence in the receiver object, returning - * the smallest index where a match occurs. - * - * If the receiver object, <code>this</code>, is an infinite sequence - * this method will not terminate if there is no match. Similarly, if - * the both the receiver object and the argument, <code>that</code> are - * infinite sequences this method will not terminate. - * - * Because both the receiver object and the argument can both potentially - * be an infinite sequences, we do not attempt to use an optimized - * searching algorithm. Therefore, the running time will be proportional - * to the length of the receiver object and the argument. Subclasses and - * traits can potentially provide an optimized implementation. - * - * @return -1 if <code>that</code> not contained in <code>this</code>, - * otherwise the smallest index where <code>that</code> is found. - * - * @see String.indexOf - */ - def indexOf[B >: A](that: Seq[B]): Int = { - val e = this.elements - // Offset into e - var i = 0 - if (that.isEmpty) return 0 - while (e.hasNext) { - if (this.startsWith(that, i)) return i - e.next; i += 1 - } - -1 - } - - /** Is <code>that</code> a slice in this? - */ - def containsSlice[B](that: Seq[B]): Boolean = indexOf(that) != -1 -} diff --git a/src/library/scala/SeqProxy.scala b/src/library/scala/SeqProxy.scala deleted file mode 100644 index 915211b2e9..0000000000 --- a/src/library/scala/SeqProxy.scala +++ /dev/null @@ -1,87 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - - -/** This class implements a proxy for sequences. It forwards - * all calls to a different sequence object. - * - * @author Martin Odersky - * @author Matthias Zenger - * @version 2.0, 31/12/2006 - */ -trait SeqProxy[+A] extends Seq[A] with CollectionProxy[A] { - - override def self: Seq[A] - - // PartialFunction delegates - - override def apply(i: Int): A = self(i) - - // Seq delegates - // Seq methods could be printed by cat Seq.scala | sed -n '/trait Seq/,$ p' | egrep '^ (override )?def' - - override def length: Int = self.length - override def lengthCompare(l: Int) = self lengthCompare l - override def size = self.size - override def isEmpty = self.isEmpty - @deprecated - override def concat [B >: A](that: Iterable[B]): Seq[B] = self concat that - override def last = self.last - override def lastOption = self.lastOption - override def first = self.first - override def firstOption = self.firstOption - @deprecated - override def headOption = firstOption - - override def ++ [B >: A](that: Iterable[B]) = self ++ that - override def isDefinedAt(x: Int): Boolean = self isDefinedAt x - - override def lastIndexOf[B >: A](elem: B): Int = self lastIndexOf elem - override def findIndexOf(p: A => Boolean): Int = self findIndexOf p - - override def indexOf[B >: A](elem: B): Int = self indexOf elem - - override def map[B](f: A => B): Seq[B] = self map f - override def flatMap[B](f: A => Iterable[B]) = self flatMap f - override def filter(p: A => Boolean): Seq[A] = self filter p - override def take(n: Int): Seq[A] = self take n - override def drop(n: Int): Seq[A] = self drop n - - override def slice(from: Int, len: Int): Seq[A] = self.slice(from, len) - @deprecated - override def slice(from: Int) = slice(from, length) - - override def takeWhile(p: A => Boolean): Seq[A] = self takeWhile p - override def dropWhile(p: A => Boolean): Seq[A] = self dropWhile p - - override def reverse: Seq[A] = self.reverse - - override def contains(elem: Any): Boolean = self contains elem - @deprecated - override def subseq(from: Int, end: Int) = slice(from, end - from) - - override def toArray[B >: A]: Array[B] = self.toArray - - override def toSeq = self.toSeq - - override def projection = self.projection - - override def equalsWith[B](that: Seq[B])(f: (A, B) => Boolean): Boolean = self.equalsWith(that)(f) - - override def startsWith[B](that: Seq[B]) = self startsWith that - override def endsWith[B](that: Seq[B]) = self endsWith that - - override def indexOf[B >: A](that: Seq[B]) = self indexOf that - - override def containsSlice[B](that: Seq[B]) = self containsSlice that -} diff --git a/src/library/scala/Stream.scala b/src/library/scala/Stream.scala deleted file mode 100644 index f3300c4afe..0000000000 --- a/src/library/scala/Stream.scala +++ /dev/null @@ -1,518 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - -import Predef._ - -/** - * The object <code>Stream</code> provides helper functions - * to manipulate streams. - * - * @author Martin Odersky, Matthias Zenger - * @version 1.1 08/08/03 - */ -object Stream { - - def apply[A](xs: A*) = (xs :\ (empty: Stream[A]))(cons(_, _)) - - def unapplySeq[A](xs: Stream[A]): Option[Seq[A]] = Some(xs) - - object lazy_:: { - def unapply[A](xs: Stream[A]): Option[(A, Stream[A])] = - if (xs.isEmpty) None - else Some(xs.head, xs.tail) - } - - /** a stream with a definite size */ - trait Definite[+A] extends Stream[A] with Function0[Stream[A]] { - override def hasDefiniteSize = true - override def apply = this - - /** Converts stream to string. Redefined here as - * super[Stream].toString does not pass because of an implementation - * restriction (super[C] cannot be called when C is a class). - */ - override def toString = - "Stream(" + addDefinedElems(new StringBuilder(), "") + ")" - } - - /** The empty stream */ - val empty: Stream[Nothing] = new Definite[Nothing] { - override def isEmpty = true - def head: Nothing = throw new NoSuchElementException("head of empty stream") - def tail: Stream[Nothing] = throw new UnsupportedOperationException("tail of empty stream") - protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder = buf - } - - object cons { - - /** A stream consisting of a given first element and remaining elements - * @param hd The first element of the result stream - * @param tl The remaining elements of the result stream - */ - def apply[A](hd: A, tl: => Stream[A]) = new Stream[A] { - override def hasDefiniteSize = if (tlDefined) tlVal.hasDefiniteSize else super.hasDefiniteSize - override def isEmpty = false - def head = hd - private var tlVal: Stream[A] = _ - private def tlDefined = tlVal ne null - def tail: Stream[A] = { - if (!tlDefined) { tlVal = tl } - tlVal - } - protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder = { - val buf1 = buf.append(prefix).append(hd) - if (tlDefined) tlVal.addDefinedElems(buf1, ", ") else buf1 append ", ?" - } - } - - def unapply[A](str: Stream[A]): Option[(A, Stream[A])] = - if(str.isEmpty) - None - else - Some((str.head, str.tail)) - } - - /** A stream containing all elements of a given iterator, in the order they are produced. - * @param it The iterator producing the stream's elements - */ - def fromIterator[A](it: Iterator[A]): Stream[A] = - if (it.hasNext) cons(it.next, fromIterator(it)) else empty - - /** The concatenation of a sequence of streams - */ - def concat[A](xs: Iterable[Stream[A]]): Stream[A] = concat(xs.elements) - - /** The concatenation of all given streams - */ - def concat[A](s1: Stream[A], s2: Stream[A], ss: Stream[A]*): Stream[A] = - s1 append s2 append concat(ss.elements) - - /** The concatenation of all streams returned by an iterator - */ - def concat[A](xs: Iterator[Stream[A]]): Stream[A] = - if (xs.hasNext) xs.next append concat(xs) - else empty - - /** - * Create a stream with element values - * <code>v<sub>n+1</sub> = v<sub>n</sub> + 1</code> - * where <code>v<sub>0</sub> = start</code> - * and <code>v<sub>i</sub> < end</code>. - * - * @param start the start value of the stream - * @param end the end value of the stream - * @return the stream starting at value <code>start</code>. - */ - def range(start: Int, end: Int): Stream[Int] = - range(start, end, 1) - - /** - * Create a stream with element values - * <code>v<sub>n+1</sub> = v<sub>n</sub> + step</code> - * where <code>v<sub>0</sub> = start</code> - * and elements are in the range between <code>start</code> (inclusive) - * and <code>end</code> (exclusive) - * - * @param start the start value of the stream - * @param end the end value of the stream - * @param step the increment value of the stream - * @return the stream starting at value <code>start</code>. - */ - final def range(start: Int, end: Int, step: Int): Stream[Int] = { - if ((step <= 0 || start < end) && (step >= 0 || start > end)) - cons(start, range(start + step, end, step)) - else - empty - } - - /** - * Create a stream with element values - * <code>v<sub>n+1</sub> = step(v<sub>n</sub>)</code> - * where <code>v<sub>0</sub> = start</code> - * and elements are in the range between <code>start</code> (inclusive) - * and <code>end</code> (exclusive) - * - * @param start the start value of the stream - * @param end the end value of the stream - * @param step the increment function of the stream, must be monotonically increasing or decreasing - * @return the stream starting at value <code>start</code>. - */ - def range(start: Int, end: Int, step: Int => Int): Stream[Int] = { - val up = step(start) > start - val down = step(start) < start - def loop(lo: Int): Stream[Int] = - if ((!up || lo < end) && (!down || lo > end)) cons(lo, loop(step(lo))) - else empty - loop(start) - } - - /** - * Create an infinite stream starting at <code>start</code> - * and incrementing by step <code>step</code> - * - * @param start the start value of the stream - * @param step the increment value of the stream - * @return the stream starting at value <code>start</code>. - */ - def from(start: Int, step: Int): Stream[Int] = - cons(start, from(start+step, step)) - - /** - * Create an infinite stream starting at <code>start</code> - * and incrementing by 1. - * - * @param start the start value of the stream - * @return the stream starting at value <code>start</code>. - */ - def from(start: Int): Stream[Int] = from(start, 1) - - /** - * Create an infinite stream containing the given element. - * - * @param elem the element composing the resulting stream - * @return the stream containing an inifinite number of elem - */ - def const[A](elem: A): Stream[A] = cons(elem, const(elem)) - - /** Create a stream containing several copies of an element. - * - * @param n the length of the resulting stream - * @param elem the element composing the resulting stream - * @return the stream composed of n elements all equal to elem - */ - def make[A](n: Int, elem: A): Stream[A] = - Stream.const(elem) take n -} - -/** - * <p>The class <code>Stream</code> implements lazy lists where elements - * are only evaluated when they are needed. Here is an example:</p> - * <pre> - * <b>object</b> Main <b>extends</b> Application { - * - * <b>def</b> from(n: Int): Stream[Int] = - * Stream.cons(n, from(n + 1)) - * - * <b>def</b> sieve(s: Stream[Int]): Stream[Int] = - * Stream.cons(s.head, sieve(s.tail filter { _ % s.head != 0 })) - * - * <b>def</b> primes = sieve(from(2)) - * - * primes take 10 print - * } - * </pre> - * - * @author Martin Odersky, Matthias Zenger - * @version 1.1 08/08/03 - */ -abstract class Stream[+A] extends Seq.Projection[A] { - - /** is this stream empty? */ - override def isEmpty: Boolean - - override def force : List[A] = toList - - /** The first element of this stream - * @throws Predef.NoSuchElementException if the stream is empty. - */ - def head: A - - /** A stream consisting of the remaining elements of this stream after the first one. - * @throws Predef.UnsupportedOperationException if the stream is empty. - */ - def tail: Stream[A] - - /** The length of this stream */ - override def length: Int = { - var len = 0 - var here = this - while (!here.isEmpty) { - len += 1 - here = here.tail - } - len - } - - /** Result of comparing <code>length</code> with operand <code>l</code>. - * returns <code>x</code> where - * <code>x < 0</code> iff <code>this.length < l</code> - * <code>x == 0</code> iff <code>this.length == l</code> - * <code>x > 0</code> iff <code>this.length > that</code>. - * - * This method is used by matching streams against right-ignoring (...,_*) patterns. - * - * This method does not call <code>Stream.length</code>, it works for <code>O(l)</code>, - * not for <code>O(length)</code> and does not force full Stream evaluation. - */ - final override def lengthCompare(l: Int) = { - if (isEmpty) 0 - l - else if (l <= 0) 1 - else tail.lengthCompare(l - 1) - } - - override def hasDefiniteSize = false - - - /** The stream resulting from the concatenation of this stream with the argument stream. - * @param rest The stream that gets appended to this stream - */ - override def append[B >: A](rest: => Iterable[B]): Stream[B] = - if (isEmpty) rest.toStream else Stream.cons(head, tail append rest) - - - /** An iterator returning the elements of this stream one by one. - */ - override def elements: Iterator[A] = new Iterator[A] { - var current = Stream.this - def hasNext: Boolean = !current.isEmpty - def next: A = { val result = current.head; current = current.tail; result } - } - - /** The stream without its last element. - * @throws Predef.UnsupportedOperationException if the stream is empty. - */ - def init: Stream[A] = - if (isEmpty) throw new UnsupportedOperationException("Stream.empty.init") - else if (tail.isEmpty) Stream.empty - else Stream.cons(head, tail.init) - - /** Returns the last element of this stream. - * - * @return the last element of the stream. - * @throws Predef.NoSuchElementException if the stream is empty. - */ - override final def last: A = - if (isEmpty) throw new NoSuchElementException("Stream.empty.last") - else - if (tail.isEmpty) head else tail.last - - /** Returns the <code>n</code>-th element of this stream. The first element - * (head of the stream) is at position 0. - * - * @param n index of the element to return - * @return the element at position <code>n</code> in this stream. - * @throws Predef.NoSuchElementException if the stream is too short. - */ - override def apply(n: Int): A = drop(n).head - - /** Returns the <code>n</code> first elements of this stream, or else the whole - * stream, if it has less than <code>n</code> elements. - * - * @param n the number of elements to take. - * @return the <code>n</code> first elements of this stream. - */ - override def take(n: Int): Stream[A] = - if (isEmpty || n <= 0) Stream.empty - else Stream.cons(head, if (n == 1) Stream.empty else (tail.take(n-1))) - - /** Returns the stream without its <code>n</code> first elements. - * If the stream has less than <code>n</code> elements, the empty stream is returned. - * - * @param n the number of elements to drop. - * @return the stream without its <code>n</code> first elements. - */ - override final def drop(n: Int): Stream[A] = { - if (isEmpty || n <= 0) this - else tail.drop(n - 1) - } - - - /** Returns the longest prefix of this stream whose elements satisfy - * the predicate <code>p</code>. - * - * @param p the test predicate. - * @return the longest prefix of this stream whose elements satisfy - * the predicate <code>p</code>. - */ - override def takeWhile(p: A => Boolean): Stream[A] = - if (isEmpty || !p(head)) Stream.empty - else Stream.cons(head, tail takeWhile p) - - /** Returns the longest suffix of this stream whose first element - * does not satisfy the predicate <code>p</code>. - * - * @param p the test predicate. - * @return the longest suffix of the stream whose first element - * does not satisfy the predicate <code>p</code>. - */ - override final def dropWhile(p: A => Boolean): Stream[A] = { - if (isEmpty || !p(head)) this - else tail.dropWhile(p) - } - - /** Returns the stream resulting from applying the given function <code>f</code> to each - * element of this stream. - * - * @param f function to apply to each element. - * @return <code>[f(a0), ..., f(an)]</code> if this stream is <code>[a0, ..., an]</code>. - */ - override def map[B](f: A => B): Stream[B] = - if (isEmpty) Stream.empty - else Stream.cons(f(head), tail map f) - - /** Apply the given function <code>f</code> to each element of this stream - * (while respecting the order of the elements). - * - * @param f the treatment to apply to each element. - */ - override final def foreach(f: A => Unit) { - if (isEmpty) {} - else { f(head); tail.foreach(f) } - } - - /** Returns all the elements of this stream that satisfy the - * predicate <code>p</code>. The order of the elements is preserved. - * - * @param p the predicate used to filter the stream. - * @return the elements of this stream satisfying <code>p</code>. - */ - override final def filter(p: A => Boolean): Stream[A] = { - if (isEmpty) this - else if (p(head)) Stream.cons(head, tail.filter(p)) - else tail.filter(p) - } - - /** Tests if the predicate <code>p</code> is satisfied by all elements - * in this stream. - * - * @param p the test predicate. - * @return <code>true</code> iff all elements of this stream satisfy the - * predicate <code>p</code>. - */ - override final def forall(p: A => Boolean): Boolean = { - if (isEmpty) true - else if (p(head)) tail.forall(p) - else false - } - - /** Tests the existence in this stream of an element that satisfies the - * predicate <code>p</code>. - * - * @param p the test predicate. - * @return <code>true</code> iff there exists an element in this stream that - * satisfies the predicate <code>p</code>. - */ - override final def exists(p: A => Boolean): Boolean = { - if (isEmpty) false - else if (p(head)) true - else tail.exists(p) - } - - /** Combines the elements of this stream together using the binary - * function <code>f</code>, from left to right, and starting with - * the value <code>z</code>. - * - * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...), - * a<sub>n</sub>)</code> if the stream is - * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>. - */ - override final def foldLeft[B](z: B)(f: (B, A) => B): B = { - if (isEmpty) z - else tail.foldLeft(f(z, head))(f) - } - - /** Combines the elements of this stream together using the binary - * function <code>f</code>, from rigth to left, and starting with - * the value <code>z</code>. - * - * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code> - * if the stream is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>. - */ - override def foldRight[B](z: B)(f: (A, B) => B): B = - if (isEmpty) z - else f(head, tail.foldRight(z)(f)) - - /** Applies the given function <code>f</code> to each element of - * this stream, then concatenates the results. - * - * @param f the function to apply on each element. - * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if - * this stream is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>. - */ - override def flatMap[B](f: A => Iterable[B]): Stream[B] = { - // drops A's for which f yields an empty Iterable[B] - def loop(s: Stream[A]): Stream[B] = { - if (s.isEmpty) - Stream.empty - else { - val i = f(s.head) - if (i isEmpty) - loop(s.tail) - else - i.toStream append loop(s.tail) - } - } - - loop(this) - } - - override def toStream = this - - /** A stream consisting of all elements of this stream in reverse order. - */ - override def reverse: Stream[A] = - foldLeft(Stream.empty: Stream[A])((xs, x) => Stream.cons(x, xs)) - - /** Fills the given array <code>xs</code> with the elements of - * this stream starting at position <code>start</code>. - * - * @param xs the array to fill. - * @param start starting index. - * @pre the array must be large enough to hold all elements. - */ - override final def copyToArray[B >: A](xs: Array[B], start: Int) { - if (!isEmpty) { xs(start) = head; tail.copyToArray(xs, start + 1) } - } - - /** Returns a stream formed from this stream and the specified stream - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * If one of the two streams is longer than the other, its remaining elements are ignored. - * - * @return <code>Stream({a<sub>0</sub>,b<sub>0</sub>}, ..., - * {a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>)}</code> when - * <code>Stream(a<sub>0</sub>, ..., a<sub>m</sub>) - * zip Stream(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked. - */ - def zip[B](that: Stream[B]): Stream[(A, B)] = - if (this.isEmpty || that.isEmpty) Stream.empty - else Stream.cons((this.head, that.head), this.tail zip that.tail) - - - /** Returns a stream that pairs each element of this stream - * with its index, counting from 0. - * - * @return the stream <code>Stream({a<sub>0</sub>,0}, {a<sub>0</sub>,1},...)</code> - * where <code>a<sub>i</sub></code> are the elements of this stream. - */ - def zipWithIndex: Stream[(A, Int)] = - zip(Stream.from(0)) - - /** Prints elements of this stream one by one, separated by commas */ - def print { print(", ") } - - /** Prints elements of this stream one by one, separated by <code>sep</code> - * @param sep The separator string printed between consecutive elements. - */ - def print(sep: String) { - if (isEmpty) Console.println("Stream.empty") - else { Console.print(head); Console.print(sep); tail.print(sep) } - } - - /** Converts stream to string */ - override def toString = - "Stream(" + addDefinedElems(new StringBuilder(), "") + ")" - - /** Write all elements of this string into given string builder */ - protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder -} diff --git a/src/library/scala/StringBuilder.scala b/src/library/scala/StringBuilder.scala deleted file mode 100644 index 3d06a96c0f..0000000000 --- a/src/library/scala/StringBuilder.scala +++ /dev/null @@ -1,935 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala - -import Predef._ - -/** <p> - * A mutable sequence of characters. This class provides an API compatible - * with <a class="java/lang/StringBuilder" href="" target="_top"> - * <code>java.lang.StringBuilder</code></a>. - * </p> - * - * @author Stephane Micheloud - * @version 1.0 - */ -@serializable -@SerialVersionUID(0 - 8525408645367278351L) -final class StringBuilder(initCapacity: Int, private val initValue: String) - extends (Int => Char) { - if (initCapacity < 0) throw new IllegalArgumentException - if (initValue eq null) throw new NullPointerException - - /** The value is used for character storage. */ - private var value = new Array[Char](initCapacity + initValue.length) - - /** The count is the number of characters used. */ - private var count: Int = 0 - - /** Constructs a string builder with no characters in it and an - * initial capacity of 16 characters. - */ - def this() = this(16, "") - - /** Constructs a string builder with no characters in it and an - * initial capacity specified by the <code>capacity</code> argument. - * - * @param capacity the initial capacity. - * @throws NegativeArraySizeException if the <code>capacity</code> - * argument is less than <code>0</code>. - */ - def this(capacity: Int) = this(capacity, "") - - def this(str: String) = this(16, str) - - append(initValue) - - def toArray: Array[Char] = value - - def length: Int = count - - def length_=(n: Int) { setLength(n) } - - /** Sets the length of the character sequence. - * - * @param newLength the new length - * @throws IndexOutOfBoundsException if the <code>n</code> argument is negative. - */ - def setLength(n: Int) { - if (n < 0) - throw new StringIndexOutOfBoundsException(n) - if (n > value.length) expandCapacity(n) - if (count < n) - while (count < n) { - value(count) = '\0'; count += 1 - } - else - count = n - } - - /** Returns the current capacity. The capacity is the amount of storage - * available for newly inserted characters, beyond which an allocation - * will occur. - * - * @return the current capacity - */ - def capacity: Int = value.length - - /** Same as <code>ensureCapacity</code>. */ - def capacity_=(n: Int) { ensureCapacity(n) } - - /** <p> - * Ensures that the capacity is at least equal to the specified minimum. - * If the current capacity is less than the argument, then a new internal - * array is allocated with greater capacity. The new capacity is the larger of: - * </p> - * <ul> - * <li>The <code>n</code> argument. - * <li>Twice the old capacity, plus <code>2</code>. - * </ul> - * <p> - * If the <code>n</code> argument is non-positive, this - * method takes no action and simply returns. - * </p> - * - * @param n the minimum desired capacity. - */ - def ensureCapacity(n: Int) { - if (n > value.length) expandCapacity(n) - } - - private def expandCapacity(n: Int) { - val newCapacity = (value.length + 1) * 2 - value = StringBuilder.copyOf( - value, - if (newCapacity < 0) Math.MAX_INT else if (n > newCapacity) n else newCapacity - ) - } - - /** <p> - * Returns the <code>Char</code> value in this sequence at the specified index. - * The first <code>Char</code> value is at index <code>0</code>, the next at index - * <code>1</code>, and so on, as in array indexing. - * </p> - * <p> - * The index argument must be greater than or equal to - * <code>0</code>, and less than the length of this sequence. - * </p> - * - * @param index the index of the desired <code>Char</code> value. - * @return the <code>Char</code> value at the specified index. - * @throws IndexOutOfBoundsException if <code>index</code> is - * negative or greater than or equal to <code>length()</code>. - */ - def charAt(index: Int): Char = { - if (index < 0 || index >= count) - throw new StringIndexOutOfBoundsException(index) - value(index) - } - - /** Same as <code>charAt</code>. */ - def apply(i: Int): Char = charAt(i) - - /** <p> - * Removes the <code>Char</code> at the specified position in this - * sequence. This sequence is shortened by one <code>Char</code>. - * </p> - * - * @param index Index of <code>Char</code> to remove - * @return This object. - * @throws StringIndexOutOfBoundsException if the <code>index</code> - * is negative or greater than or equal to <code>length()</code>. - */ - def deleteCharAt(index: Int): StringBuilder = { - if (index < 0 || index >= count) - throw new StringIndexOutOfBoundsException(index) - compat.Platform.arraycopy(value, index + 1, value, index, count - index - 1) - count -= 1 - this - } - - /** <p> - * The character at the specified index is set to <code>ch</code>. This - * sequence is altered to represent a new character sequence that is - * identical to the old character sequence, except that it contains the - * character <code>ch</code> at position <code>index</code>. - * </p> - * <p> - * The index argument must be greater than or equal to - * <code>0</code>, and less than the length of this sequence. - * </p> - * - * @param index the index of the character to modify. - * @param ch the new character. - * @throws IndexOutOfBoundsException if <code>index</code> is - * negative or greater than or equal to <code>length()</code>. - */ - def setCharAt(index: Int, ch: Char) { - if (index < 0 || index >= count) - throw new StringIndexOutOfBoundsException(index) - value(index) = ch - } - - /** Same as <code>setCharAt</code>. */ - def update(i: Int, c: Char) { setCharAt(i, c) } - - /** Returns a new <code>String</code> that contains a subsequence of - * characters currently contained in this character sequence. The - * substring begins at the specified index and extends to the end of - * this sequence. - * - * @param start The beginning index, inclusive. - * @return The new string. - * @throws StringIndexOutOfBoundsException if <code>start</code> is - * less than zero, or greater than the length of this object. - */ - def substring(start: Int): String = substring(start, count) - - /** Returns a new <code>String</code> that contains a subsequence of - * characters currently contained in this sequence. The - * substring begins at the specified <code>start</code> and - * extends to the character at index <code>end - 1</code>. - * - * @param start The beginning index, inclusive. - * @param end The ending index, exclusive. - * @return The new string. - * @throws StringIndexOutOfBoundsException if <code>start</code> - * or <code>end</code> are negative or greater than - * <code>length()</code>, or <code>start</code> is - * greater than <code>end</code>. - */ - def substring(start: Int, end: Int): String = { - if (start < 0) - throw new StringIndexOutOfBoundsException(start) - if (end > count) - throw new StringIndexOutOfBoundsException(end) - if (start > end) - throw new StringIndexOutOfBoundsException(end - start) - new String(value, start, end - start) - } - - /** <p> - * Appends the string representation of the <code>Any</code> - * argument. - * </p> - * <p> - * The argument is converted to a string as if by the method - * <code>String.valueOf</code>, and the characters of that - * string are then appended to this sequence. - * </p> - * - * @param x an <code>Any</code> object. - * @return a reference to this object. - */ - def append(x: Any): StringBuilder = - append(String.valueOf(x)) - - /** Appends the specified string to this character sequence. - * - * @param s a string. - * @return a reference to this object. - */ - def append(s: String): StringBuilder = { - val str = if (s == null) "null" else s - val len = str.length - if (len > 0) { - val newCount = count + len - if (newCount > value.length) expandCapacity(newCount) - str.getChars(0, len, value, count) - count = newCount - } - this - } - - /** Appends the specified string builder to this sequence. - * - * @param sb - * @return - */ - def append(sb: StringBuilder): StringBuilder = - if (sb == null) - append("null") - else { - val len = sb.length - val newCount = count + len - if (newCount > value.length) expandCapacity(newCount) - compat.Platform.arraycopy(sb.toArray, 0, value, count, len) - count = newCount - this - } - - /** <p> - * Appends the string representation of the <code>Char</code> sequence - * argument to this sequence. - * </p> - * <p> - * The characters of the sequence argument are appended, in order, - * to the contents of this sequence. The length of this sequence - * increases by the length of the argument. - * </p> - * - * @param x the characters to be appended. - * @return a reference to this object. - */ - def append(x: Seq[Char]): StringBuilder = - append(x.toArray, 0, x.length) - - /** <p> - * Appends the string representation of the <code>Char</code> array - * argument to this sequence. - * </p> - * <p> - * The characters of the array argument are appended, in order, to - * the contents of this sequence. The length of this sequence - * increases by the length of the argument. - * </p> - * - * @param x the characters to be appended. - * @return a reference to this object. - */ - def append(x: Array[Char]): StringBuilder = - append(x, 0, x.length) - - /** <p> - * Appends the string representation of a subarray of the - * <code>char</code> array argument to this sequence. - * </p> - * <p> - * Characters of the <code>Char</code> array <code>x</code>, starting at - * index <code>offset</code>, are appended, in order, to the contents - * of this sequence. The length of this sequence increases - * by the value of <code>len</code>. - * </p> - * - * @param x the characters to be appended. - * @param offset the index of the first <code>Char</code> to append. - * @param len the number of <code>Char</code>s to append. - * @return a reference to this object. - */ - def append(x: Array[Char], offset: Int, len: Int): StringBuilder = { - val newCount = count + len - if (newCount > value.length) expandCapacity(newCount) - compat.Platform.arraycopy(x, offset, value, count, len) - count = newCount - this - } - - /** <p> - * Appends the string representation of the <code>Boolean</code> - * argument to the sequence. - * </p> - * <p> - * The argument is converted to a string as if by the method - * <code>String.valueOf</code>, and the characters of that - * string are then appended to this sequence. - * </p> - * - * @param x a <code>Boolean</code>. - * @return a reference to this object. - */ - def append(x: Boolean): StringBuilder = { - if (x) { - val newCount = count + 4 - if (newCount > value.length) expandCapacity(newCount) - value(count) = 't'; count += 1 - value(count) = 'r'; count += 1 - value(count) = 'u'; count += 1 - value(count) = 'e'; count += 1 - } else { - val newCount = count + 5 - if (newCount > value.length) expandCapacity(newCount) - value(count) = 'f'; count += 1 - value(count) = 'a'; count += 1 - value(count) = 'l'; count += 1 - value(count) = 's'; count += 1 - value(count) = 'e'; count += 1 - } - this - } - - def append(x: Byte): StringBuilder = - append(String.valueOf(x)) - - def append(x: Char): StringBuilder = { - val newCount = count + 1 - if (newCount > value.length) expandCapacity(newCount) - value(count) = x; count += 1 - this - } - - def append(x: Short): StringBuilder = - append(String.valueOf(x)) - - def append(x: Int): StringBuilder = - append(String.valueOf(x)) - - def append(x: Long): StringBuilder = - append(String.valueOf(x)) - - def append(x: Float): StringBuilder = - append(String.valueOf(x)) - - def append(x: Double): StringBuilder = - append(String.valueOf(x)) - - /** Removes the characters in a substring of this sequence. - * The substring begins at the specified <code>start</code> and extends to - * the character at index <code>end - 1</code> or to the end of the - * sequence if no such character exists. If - * <code>start</code> is equal to <code>end</code>, no changes are made. - * - * @param start The beginning index, inclusive. - * @param end The ending index, exclusive. - * @return This object. - * @throws StringIndexOutOfBoundsException if <code>start</code> - * is negative, greater than <code>length()</code>, or - * greater than <code>end</code>. - */ - def delete(start: Int, end: Int): StringBuilder = { - if (start < 0 || start > end) - throw new StringIndexOutOfBoundsException(start) - val end0 = if (end > count) count else end - val len = end0 - start - if (len > 0) { - compat.Platform.arraycopy(value, start + len, value, start, count - end0) - count -= len - } - this - } - - /** Replaces the characters in a substring of this sequence - * with characters in the specified <code>String</code>. The substring - * begins at the specified <code>start</code> and extends to the character - * at index <code>end - 1</code> or to the end of the sequence if no such - * character exists. First the characters in the substring are removed and - * then the specified <code>String</code> is inserted at <code>start</code>. - * - * @param start The beginning index, inclusive. - * @param end The ending index, exclusive. - * @param str String that will replace previous contents. - * @return This object. - * @throws StringIndexOutOfBoundsException if <code>start</code> - * is negative, greater than <code>length()</code>, or - * greater than <code>end</code>. - */ - def replace(start: Int, end: Int, str: String) { - if (start < 0 || start > count || start > end) - throw new StringIndexOutOfBoundsException(start) - - val end0 = if (end > count) count else end - val len = str.length() - val newCount = count + len - (end0 - start) - if (newCount > value.length) expandCapacity(newCount) - - compat.Platform.arraycopy(value, end, value, start + len, count - end) - str.getChars(0, len, value, start) - count = newCount - this - } - - /** Inserts the string representation of a subarray of the <code>str</code> - * array argument into this sequence. The subarray begins at the specified - * <code>offset</code> and extends <code>len</code> <code>char</code>s. - * The characters of the subarray are inserted into this sequence at - * the position indicated by <code>index</code>. The length of this - * sequence increases by <code>len</code> <code>Char</code>s. - * - * @param index position at which to insert subarray. - * @param str a <code>Char</code> array. - * @param offset the index of the first <code>char</code> in subarray to - * be inserted. - * @param len the number of <code>Char</code>s in the subarray to - * be inserted. - * @return This object - * @throws StringIndexOutOfBoundsException if <code>index</code> - * is negative or greater than <code>length()</code>, or - * <code>offset</code> or <code>len</code> are negative, or - * <code>(offset+len)</code> is greater than - * <code>str.length</code>. - */ - def insert(index: Int, str: Array[Char], offset: Int, len: Int): StringBuilder = { - if (index < 0 || index > count) - throw new StringIndexOutOfBoundsException(index) - if (offset < 0 || len < 0 || offset > str.length - len) - throw new StringIndexOutOfBoundsException( - "offset " + offset + ", len " + len + - ", str.length " + str.length) - val newCount = count + len - if (newCount > value.length) expandCapacity(newCount) - compat.Platform.arraycopy(value, index, value, index + len, count - index) - compat.Platform.arraycopy(str, offset, value, index, len) - count = newCount - this - } - - /** <p> - * Inserts the string representation of the <code>Any</code> - * argument into this character sequence. - * </p> - * <p> - * The second argument is converted to a string as if by the method - * <code>String.valueOf</code>, and the characters of that - * string are then inserted into this sequence at the indicated - * offset. - * </p> - * <p> - * The offset argument must be greater than or equal to - * <code>0</code>, and less than or equal to the length of this - * sequence. - * </p> - * - * @param offset the offset. - * @param x an <code>Any</code> value. - * @return a reference to this object. - * @throws StringIndexOutOfBoundsException if the offset is invalid. - */ - def insert(at: Int, x: Any): StringBuilder = - insert(at, String.valueOf(x)) - - /** Inserts the string into this character sequence. - * - * @param at the offset position. - * @param x a string. - * @return a reference to this object. - * @throws StringIndexOutOfBoundsException if the offset is invalid. - */ - def insert(at: Int, x: String): StringBuilder = { - if (at < 0 || at > count) - throw new StringIndexOutOfBoundsException(at) - val str = if (x == null) "null" else x - val len = str.length - val newCount = count + len - if (newCount > value.length) expandCapacity(newCount) - compat.Platform.arraycopy(value, at, value, at + len, count - at) - str.getChars(0, len, value, at) - count = newCount - this - } - - /** Inserts the string representation of the <code>Char</code> sequence - * argument into this sequence. - * - * @param at the offset position. - * @param x a character sequence. - * @return a reference to this object. - * @throws StringIndexOutOfBoundsException if the offset is invalid. - */ - def insert(at: Int, x: Seq[Char]): StringBuilder = - insert(at, x.toArray) - - /** Inserts the string representation of the <code>Char</code> array - * argument into this sequence. - * - * @param at the offset position. - * @param x a character array. - * @return a reference to this object. - * @throws StringIndexOutOfBoundsException if the offset is invalid. - */ - def insert(at: Int, x: Array[Char]): StringBuilder = { - if (at < 0 || at > count) - throw new StringIndexOutOfBoundsException(at) - val len = x.length - val newCount = count + len - if (newCount > value.length) expandCapacity(newCount) - compat.Platform.arraycopy(value, at, value, at + len, count - at) - compat.Platform.arraycopy(x, 0, value, at, len) - count = newCount - this - } - - /** <p> - * Inserts the string representation of the <code>Boolean</code> argument - * into this sequence. - * </p> - * <p> - * The offset argument must be greater than or equal to 0, and less than - * or equal to the length of this sequence. - * </p> - * - * @param at the offset position. - * @param x a <code>Boolean</code> value. - * @return a reference to this object. - */ - def insert(at: Int, x: Boolean): StringBuilder = - insert(at, String.valueOf(x)) - - /** <p> - * Inserts the string representation of the <code>Byte</code> argument - * into this sequence. - * </p> - * <p> - * The offset argument must be greater than or equal to 0, and less than - * or equal to the length of this sequence. - * </p> - * - * @param at the offset position. - * @param x a <code>Byte</code> value. - * @return a reference to this object. - */ - def insert(at: Int, x: Byte): StringBuilder = - insert(at, String.valueOf(x)) - - /** <p> - * Inserts the string representation of the <code>Char</code> argument - * into this sequence. - * </p> - * <p> - * The offset argument must be greater than or equal to 0, and less than - * or equal to the length of this sequence. - * </p> - * - * @param at the offset position. - * @param x a <code>Char</code> value. - * @return a reference to this object. - */ - def insert(at: Int, x: Char): StringBuilder = { - if (at < 0 || at > count) - throw new StringIndexOutOfBoundsException(at) - val newCount = count + 1 - if (newCount > value.length) expandCapacity(newCount) - compat.Platform.arraycopy(value, at, value, at + 1, count - at) - value(at) = x - count = newCount - this - } - - /** <p> - * Inserts the string representation of the <code>Short</code> argument - * into this sequence. - * </p> - * <p> - * The offset argument must be greater than or equal to 0, and less than - * or equal to the length of this sequence. - * </p> - * - * @param at the offset position. - * @param x a <code>Short</code> value. - * @return a reference to this object. - */ - def insert(at: Int, x: Short): StringBuilder = - insert(at, String.valueOf(x)) - - /** <p> - * Inserts the string representation of the <code>Int</code> argument - * into this sequence. - * </p> - * <p> - * The offset argument must be greater than or equal to 0, and less than - * or equal to the length of this sequence. - * </p> - * - * @param at the offset position. - * @param x a <code>Int</code> value. - * @return a reference to this object. - */ - def insert(at: Int, x: Int): StringBuilder = - insert(at, String.valueOf(x)) - - /** <p> - * Inserts the string representation of the <code>Long</code> argument - * into this sequence. - * </p> - * <p> - * The offset argument must be greater than or equal to 0, and less than - * or equal to the length of this sequence. - * </p> - * - * @param at the offset position. - * @param x a <code>Long</code> value. - * @return a reference to this object. - */ - def insert(at: Int, x: Long): StringBuilder = - insert(at, String.valueOf(x)) - - /** <p> - * Inserts the string representation of the <code>Float</code> argument - * into this sequence. - * </p> - * <p> - * The offset argument must be greater than or equal to 0, and less than - * or equal to the length of this sequence. - * </p> - * - * @param at the offset position. - * @param x a <code>Float</code> value. - * @return a reference to this object. - */ - def insert(at: Int, x: Float): StringBuilder = - insert(at, String.valueOf(x)) - - /** <p> - * Inserts the string representation of the <code>Double</code> argument - * into this sequence. - * </p> - * <p> - * The offset argument must be greater than or equal to 0, and less than - * or equal to the length of this sequence. - * </p> - * - * @param at the offset position. - * @param x a <code>Double</code> value. - * @return a reference to this object. - */ - def insert(at: Int, x: Double): StringBuilder = - insert(at, String.valueOf(x)) - - /** <p> - * Returns the index within this string of the first occurrence of the - * specified substring. The integer returned is the smallest value - * <i>k</i> such that: - * </p> - * <blockquote><pre> - * this.toString().startsWith(str, <i>k</i>)</pre> - * </blockquote> - * <p> - * is <code>true</code>. - * </p> - * - * @param str any string. - * @return if the string argument occurs as a substring within this - * object, then the index of the first character of the first - * such substring is returned; if it does not occur as a - * substring, <code>-1</code> is returned. - * @throws NullPointerException if <code>str</code> is <code>null</code>. - */ - def indexOf(str: String): Int = indexOf(str, 0) - - /** <p> - * Returns the index within this string of the first occurrence of the - * specified substring, starting at the specified index. The integer - * returned is the smallest value <code>k</code> for which: - * </p><pre> - * k >= Math.min(fromIndex, str.length()) && - * this.toString().startsWith(str, k)</pre> - * <p> - * If no such value of <code>k</code> exists, then <code>-1</code> - * is returned. - * </p> - * - * @param str the substring for which to search. - * @param fromIndex the index from which to start the search. - * @return the index within this string of the first occurrence - * of the specified substring, starting at the specified index. - */ - def indexOf(str: String, fromIndex: Int): Int = - StringBuilder.indexOf(value, 0, count, str.toCharArray, 0, str.length(), fromIndex) - - /** <p> - * Returns the index within this string of the rightmost occurrence - * of the specified substring. The rightmost empty string "" is - * considered to occur at the index value <code>this.length()</code>. - * The returned index is the largest value <i>k</i> such that - * </p> - * <blockquote><pre> - * this.toString().startsWith(str, k)</pre> - * </blockquote> - * <p> - * is true. - * </p> - * - * @param str the substring to search for. - * @return if the string argument occurs one or more times as a substring - * within this object, then the index of the first character of - * the last such substring is returned. If it does not occur as - * a substring, <code>-1</code> is returned. - * @throws NullPointerException if <code>str</code> is <code>null</code>. - */ - def lastIndexOf(str: String): Int = lastIndexOf(str, count) - - /** <p> - * Returns the index within this string of the last occurrence of the - * specified substring. The integer returned is the largest value - * <code>k</code> such that: - * </p><pre> - * k <= Math.min(fromIndex, str.length()) && - * this.toString().startsWith(str, k)</pre> - * <p> - * If no such value of <code>k</code> exists, then <code>-1</code> - * is returned. - * </p> - * - * @param str the substring to search for. - * @param fromIndex the index to start the search from. - * @return the index within this sequence of the last occurrence - * of the specified substring. - */ - def lastIndexOf(str: String, fromIndex: Int): Int = - StringBuilder.lastIndexOf(value, 0, count, str.toCharArray, 0, str.length(), fromIndex) - - /** <p> - * Causes this character sequence to be replaced by the reverse of the - * sequence. If there are any surrogate pairs included in the sequence, - * these are treated as single characters for the reverse operation. - * Thus, the order of the high-low surrogates is never reversed. - * </p> - * <p> - * Let <i>n</i> be the character length of this character sequence - * (not the length in <code>Char</code> values) just prior to - * execution of the <code>reverse</code> method. Then the - * character at index <i>k</i> in the new character sequence is - * equal to the character at index <i>n-k-1</i> in the old - * character sequence. - * </p> - * - * @return a reference to this object. - */ - def reverse(): StringBuilder = { - var hasSurrogate = false - val n = count - 1 - var j = (n-1) >> 1 - while (j >= 0) { - val temp = value(j) - val temp2 = value(n - j) - if (!hasSurrogate) - hasSurrogate = - (temp >= Character.MIN_HIGH_SURROGATE && temp <= Character.MAX_LOW_SURROGATE) || - (temp2 >= Character.MIN_HIGH_SURROGATE && temp2 <= Character.MAX_LOW_SURROGATE) - value(j) = temp2 - value(n - j) = temp - j -= 1 - } - if (hasSurrogate) { - // Reverse back all valid surrogate pairs - var i = 0 - while (i < count - 1) { - val c2 = value(i) - if (Character.isLowSurrogate(c2)) { - val c1 = value(i + 1) - if (Character.isHighSurrogate(c1)) { - value(i) = c1; i += 1 - value(i) = c2 - } - } - i += 1 - } - } - this - } - - /** Returns a string representing the data in this sequence. - * A new <code>String</code> object is allocated and initialized to - * contain the character sequence currently represented by this - * object. This <code>String</code> is then returned. Subsequent - * changes to this sequence do not affect the contents of the - * <code>String</code>. - * - * @return a string representation of this sequence of characters. - */ - override def toString(): String = new String(value, 0, count) - - @throws(classOf[java.io.IOException]) - private def writeObject(s: java.io.ObjectOutputStream) { - s.defaultWriteObject() - s.writeInt(count) - s.writeObject(value) - } - - @throws(classOf[java.io.IOException]) - private def readObject(s: java.io.ObjectInputStream ) { - s.defaultReadObject() - count = s.readInt() - value = s.readObject().asInstanceOf[Array[Char]] - } - -} - - -object StringBuilder -{ - // method <code>java.util.Arrays.copyOf</code> exists since 1.6 - private def copyOf(src: Array[Char], newLength: Int): Array[Char] = { - val dest = new Array[Char](newLength) - compat.Platform.arraycopy(src, 0, dest, 0, Math.min(src.length, newLength)) - dest - } - - private def indexOf(source: Array[Char], sourceOffset: Int, sourceCount: Int, - target: Array[Char], targetOffset: Int, targetCount: Int, - fromIndex: Int): Int = - if (fromIndex >= sourceCount) - if (targetCount == 0) sourceCount else -1 - else { - val inx = if (fromIndex < 0) 0 else fromIndex - if (targetCount == 0) - inx - else { - val first = target(targetOffset) - val max = sourceOffset + (sourceCount - targetCount) - - var i = sourceOffset + inx - while (i <= max) { - /* Look for first character. */ - if (source(i) != first) { - i += 1 - while (i <= max && source(i) != first) i += 1 - } - /* Found first character, now look at the rest of v2 */ - if (i <= max) { - var j = i + 1 - val end = j + targetCount - 1 - var k = targetOffset + 1 - while (j < end && source(j) == target(k)) { - j += 1 - k += 1 - } - if (j == end) { - /* Found whole string. */ - return i - sourceOffset - } - } // if - i += 1 - } // while - -1 - } - } - - private def lastIndexOf(source: Array[Char], sourceOffset: Int, sourceCount: Int, - target: Array[Char], targetOffset: Int, targetCount: Int, - fromIndex: Int): Int = { - val rightIndex = sourceCount - targetCount - if (fromIndex < 0) return -1 - val inx = if (fromIndex > rightIndex) rightIndex else fromIndex - // Empty string always matches - if (targetCount == 0) return inx - - val strLastIndex = targetOffset + targetCount - 1 - val strLastChar = target(strLastIndex) - val min = sourceOffset + targetCount - 1 - var i = min + fromIndex - - while (true) { - while (i >= min && source(i) != strLastChar) i -= 1 - if (i < min) return -1 - var j = i - 1 - val start = j - (targetCount - 1) - var k = strLastIndex - 1 - var outerWhile = false - while (j > start && !outerWhile) { - if (source(j) != target(k)) { - j -= 1 - k -= 1 - i -= 1 - outerWhile = true - } - } - if (!outerWhile) return start - sourceOffset + 1 - } - -1 - } - - implicit def toCharSequence(sb: StringBuilder): java.lang.CharSequence = new java.lang.CharSequence { - def length: Int = sb.length - def charAt(index: Int): Char = sb.charAt(index) - def subSequence(start: Int, end: Int): java.lang.CharSequence = sb.substring(start, end) - override def toString: String = sb.toString - } -} diff --git a/src/library/scala/Symbol.scala b/src/library/scala/Symbol.scala index e1a1c66bd4..becb37bc96 100644 --- a/src/library/scala/Symbol.scala +++ b/src/library/scala/Symbol.scala @@ -11,9 +11,12 @@ package scala -import scala.collection.jcl +// jcl disabled for now; go directly to java collections. +//import scala.collection.jcl -private[scala] object internedSymbols extends jcl.WeakHashMap[String, ref.WeakReference[Symbol]] +//private[scala] object internedSymbols extends jcl.WeakHashMap[String, ref.WeakReference[Symbol]] +private[scala] object internedSymbols + extends java.util.WeakHashMap[String, java.lang.ref.WeakReference[Symbol]] /** <p> * This class provides a simple way to get unique objects for @@ -56,13 +59,20 @@ object Symbol { * @return the unique reference to this string. */ def apply(name: String): Symbol = internedSymbols.synchronized { - internedSymbols.get(name).flatMap(_.get) match { - case Some(sym) => sym - case _ => - val sym = new Symbol(name) - internedSymbols(name) = new ref.WeakReference(sym) - sym +// internedSymbols.get(name).flatMap(_.get) match { +// case Some(sym) => sym +// case _ => +// val sym = new Symbol(name) +// internedSymbols(name) = new ref.WeakReference(sym) +// sym + var sym: Symbol = null + val ref = internedSymbols.get(name) + if (ref != null) sym = ref.get + if (sym == null) { + sym = new Symbol(name) + internedSymbols.put(name, new java.lang.ref.WeakReference(sym)) } + sym } def unapply(other: Symbol): Option[String] = Some(other.name) diff --git a/src/library/scala/Tuple2.scala b/src/library/scala/Tuple2.scala index e04a1b11c8..ccf8f189d5 100644 --- a/src/library/scala/Tuple2.scala +++ b/src/library/scala/Tuple2.scala @@ -1,7 +1,7 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -13,6 +13,73 @@ package scala +import annotation.unchecked.uncheckedVariance + +object Tuple2 { + + import collection.generic._ +/* !!! todo: enable + class IterableOps[CC[+B] <: Iterable[B] with IterableTemplate[CC, B @uncheckedVariance], A1, A2](tuple: (CC[A1], Iterable[A2])) { + def zip: CC[(A1, A2)] = { + val elems1 = tuple._1.elements + val elems2 = tuple._2.elements + val b = (tuple._1: IterableTemplate[CC, A1]).newBuilder[(A1, A2)] + // : needed because otherwise it picks Iterable's builder. + while (elems1.hasNext && elems2.hasNext) + b += ((elems1.next, elems2.next)) + b.result + } + def map[B](f: (A1, A2) => B): CC[B] = { + val elems1 = tuple._1.elements + val elems2 = tuple._2.elements + val b = (tuple._1: IterableTemplate[CC, A1]).newBuilder[B] + while (elems1.hasNext && elems2.hasNext) + b += f(elems1.next, elems2.next) + b.result + } + def flatMap[B](f: (A1, A2) => CC[B]): CC[B] = { + val elems1 = tuple._1.elements + val elems2 = tuple._2.elements + val b = (tuple._1: IterableTemplate[CC, A1]).newBuilder[B] + while (elems1.hasNext && elems2.hasNext) + b ++= f(elems1.next, elems2.next) + b.result + } + def foreach(f: (A1, A2) => Unit) { + val elems1 = tuple._1.elements + val elems2 = tuple._2.elements + while (elems1.hasNext && elems2.hasNext) + f(elems1.next, elems2.next) + } + def forall(p: (A1, A2) => Boolean): Boolean = { + val elems1 = tuple._1.elements + val elems2 = tuple._2.elements + while (elems1.hasNext && elems2.hasNext) + if (!p(elems1.next, elems2.next)) return false + true + } + def exists(p: (A1, A2) => Boolean): Boolean = { + val elems1 = tuple._1.elements + val elems2 = tuple._2.elements + while (elems1.hasNext && elems2.hasNext) + if (p(elems1.next, elems2.next)) return true + false + } + } + implicit def tupleOfIterableWrapper[CC[+B] <: Iterable[B] with IterableTemplate[CC, B], A1, A2](tuple: (CC[A1], Iterable[A2])) = + new IterableOps[CC, A1, A2](tuple) + + +/* A more general version which will probably not work. + implicit def tupleOfIterableWrapper[CC[+B] <: Iterable[B] with IterableTemplate[CC, B], A1, A2, B1 <: CC[A1]](tuple: B1, Iterable[A2]) = + new IterableOps[CC, A1, A2](tuple) +*/ + + // Adriaan: If you drop the type parameters it will infer the wrong types. + tupleOfIterableWrapper[collection.immutable.List, Int, Int]((collection.immutable.Nil, collection.immutable.Nil)) forall (_ + _ < 10) +*/ +} + /** Tuple2 is the canonical representation of a @see Product2 * */ diff --git a/src/library/scala/Unhashable.scala b/src/library/scala/Unhashable.scala new file mode 100644 index 0000000000..a89d331875 --- /dev/null +++ b/src/library/scala/Unhashable.scala @@ -0,0 +1,30 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala + +/** A marker trait for data structures that cannot be hashed, for instance + * because they are mutable and at the same time support structural equaality, so hashing them + * would lead to unpredictable results. + * Such data structures have `hashCode` throw an UnsupportedOperationException. They retain + * the original object hashcode with `identityHashCode`. + */ +trait Unhashable extends Object { + + /** The hashCode method always yields an error, since it is not + * safe to use sets as keys in hash tables. + * + * @return never. + */ + override def hashCode: Int = + throw new UnsupportedOperationException("unsuitable as hash key") + + /** The identity hash code is the original hash code inherited from Object. + */ + def identityHashCode: Int = + super/*[Object]*/.hashCode // !!! super[Object] does not work here +} diff --git a/src/library/scala/collection/BitSet.scala b/src/library/scala/collection/BitSet.scala index e8a4f3203a..2fb469e680 100644 --- a/src/library/scala/collection/BitSet.scala +++ b/src/library/scala/collection/BitSet.scala @@ -11,147 +11,21 @@ package scala.collection -/** <p> - * The class <code>BitSet</code> provides the interface for a space-efficient - * implementation of dense integer sets represented as bits in array of - * integers. Bit indices are between <code>0..(capacity-1)</code> inclusive. - * </p> - * - * @author Burak Emir, Stephane Micheloud, Nikolay Mihaylov - * @author Martin Odersky - * @version 2.0 01/01/2007 - */ - -abstract class BitSet extends Set[Int] { - - import compat.Platform.arraycopy - - /** number of bits in this bitset */ - def size: Int - - /** - * @param i ... - * @return <code>true</code> if bit <code>i</code> is set. - */ - def contains(i: Int): Boolean = { - (i < capacity) && { - val j = offset(i) - (0 <= j) && (j < arr.length) && - ((arr(j) & mask(i)) != 0) - } - } - - def capacity: Int - - protected def arr: Array[Int] - - /** returns an iterator over the truth values of all bits */ - final def elements: Iterator[Int] = new Iterator[Int] { - var i = 0 - def findNext: Unit = { - while (!BitSet.this.contains(i) && (i < capacity)) - i = i + 1 - } - findNext - def hasNext: Boolean = i < capacity - def next(): Int = { val j = i; i = i + 1; findNext; j } - } - +import generic._ - /** - * @return a copy of the array underlying this bitset - */ - /* - def toArray: Array[Int] = { - val length = memsize(capacity) - val newarr = new Array[Int](length) - if (arr.length > 0) - arraycopy(this.arr, 0, newarr, 0, length) - newarr - }*/ - - /** Checks if two bitsets are structurally identical. - * Uses accelerated (32 x faster) check if the other set is a BitSet - * - * @param other ... - * @return <code>true</code>, iff both bitsets contain the same - * elements. - */ - override def equals(other: Any): Boolean = other match { - case that: BitSet => - (size == that.size) && { - var len = memsize(Math.min(this.capacity, that.capacity)) - var i = 0 - while (i < len && arr(i) == that.arr(i)) i = i + 1 - i == len - } - case _ => - super.equals(other) - } - - override def hashCode(): Int = { - val len = memsize(this.capacity) - var h = 0 - var i = 0 - while (i < len) { h = h * 41 + arr(i); i = i + 1 } - h - } - - /** Checks if this set is a subset of set <code>that</code>. - * Uses accelerated (32 x faster) check if the other set is a BitSet - * - * @param other another set. - * @return <code>true</code>, iff the other set is a superset of - * this set. - */ - override def subsetOf(other: Set[Int]): Boolean = other match { - case that: BitSet => - val thisLen = memsize(this.capacity) - val thatLen = memsize(that.capacity) - val minLen = Math.min(thisLen, thatLen) - var i = 0 - while (i < minLen && that.arr(i) == (that.arr(i) | arr(i))) i = i + 1 - while (i < thisLen && arr(i) == 0) i = i + 1 - i == thisLen - case _ => - super.subsetOf(other) - } - - /** - * @param n the number of bits to be stored. - * @return the number of <code>Int</code> cells needed to store - * <code>n</code> bits. - */ - protected final def memsize(n: Int): Int = offset(n + 31) - - /** - * @param n ... - * @return the number of bits represented by <code>n</code> words. - */ - protected final def nbits(n: Int): Int = n << 5 - - /** - * @param n ... - * @return the position in the array where the bit resides. - */ - protected final def offset(n: Int): Int = n >>> 5 +/** common base class for mutable and immutable bit sets + */ +trait BitSet extends Set[Int] with BitSetTemplate[BitSet] { + override def empty = BitSet.empty +} - /** - * @param n ... - * @return a mask with 1 at the position of the bit. - */ - protected final def mask(n: Int): Int = 1 << (n & 0x1F) +/** A factory object for bitsets */ +object BitSet { - /** - * @return a copy of the array underlying this bitset - */ - def underlying : Array[Int] = { - val length = memsize(capacity) - val newarr = new Array[Int](length) - if (arr.length > 0) - arraycopy(this.arr, 0, newarr, 0, length) - newarr - } + /** The empty bitset */ + val empty: BitSet = immutable.BitSet.empty - protected override def stringPrefix = "Set" + /** A bitset containing given elements */ + def apply(elems: Int*) = immutable.BitSet.apply(elems: _*) } + diff --git a/src/library/scalax/collection/BufferedIterator.scala b/src/library/scala/collection/BufferedIterator.scala index dbe4fd36d1..f990cb8748 100755 --- a/src/library/scalax/collection/BufferedIterator.scala +++ b/src/library/scala/collection/BufferedIterator.scala @@ -9,9 +9,9 @@ // $Id: BufferedIterator.scala 12641 2007-08-22 16:01:57Z mcdirmid $ -package scalax.collection +package scala.collection -/** Buffered iterators are iterators which allow to inspect the next +/** Buffered iterators are iterators which provide a method `head` that inspects the next * element without discarding it. * * @author Martin Odersky diff --git a/src/library/scala/collection/DefaultMap.scala b/src/library/scala/collection/DefaultMap.scala new file mode 100644 index 0000000000..c188c45a45 --- /dev/null +++ b/src/library/scala/collection/DefaultMap.scala @@ -0,0 +1,37 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Map.scala 17537 2009-04-20 18:37:37Z odersky $ + + +package scala.collection + +import generic._ + +/* A default map which implements the `add` and `-` methods of maps. + * Instances that inherit from DefaultMap[A, B] still have to define: + * + * def get(key: A): Option[B] + * def elements: Iterator[(A, B)] + * + * It refers back to the original map. + * + * It might also be advisable to override `foreach` or `size` if efficient + * implementations can be found. + */ +trait DefaultMap[A, +B] extends Map[A, B] { self => + + /** A default implementation which creates a new immutable map. + */ + override def add[B1 >: B](key: A, value: B1): Map[A, B1] = + Map[A, B1]() ++ this + ((key, value)) + + /** A default implementation which creates a new immutable map. + */ + override def - (key: A): Map[A, B] = Map[A, B]() ++ this - key +} diff --git a/src/library/scala/collection/Iterable.scala b/src/library/scala/collection/Iterable.scala new file mode 100755 index 0000000000..502e7d95f4 --- /dev/null +++ b/src/library/scala/collection/Iterable.scala @@ -0,0 +1,95 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ + +package scala.collection + +import util.control.Breaks._ +// import immutable.Stream +import generic._ + +/** A template trait for iterable collections. + * + * Collection classes mixing in this trait provide a method + * <code>elements</code> which returns an iterator over all the + * elements contained in the collection. They also provide a method `newBuilder` + * which creates a builder for collections of the same kind. + * + * This trait implements Traversible's `foreach` method by stepping through + * all elements. Subclasses of `Iterable` should re-implement `foreach` with + * something more efficient, if possible. + * + * This trait adds methods `elements`, `zip`, `zipAll`, `zipWithIndex`, `sameElements`, + * `takeRight`, `dropRight` to the methods inherited from trait `Traversible`. + * + * @author Martin Odersky + * @version 2.8 + */ +trait Iterable[+A] extends Traversible[A] with IterableTemplate[A, Iterable[A]] { + override protected[this] def newBuilder = Iterable.newBuilder + override def traversibleBuilder[B]: Builder[B, Iterable[B], Any] = Iterable.newBuilder[B] + + /* The following methods are inherited from trait IterableTemplate + * + override def elements: Iterator[A] + override def takeRight(n: Int): Iterable[A] + override def dropRight(n: Int): Iterable[A] + override def sameElements[B >: A](that: Iterable[B]): Boolean + override def view + override def view(from: Int, until: Int) + */ +} + +/** Factory methods and utilities for instances of type Traversible */ +object Iterable extends TraversibleFactory[Iterable] { + + type Coll = Iterable[_] + implicit def builderFactory[A]: BuilderFactory[A, Iterable[A], Coll] = new BuilderFactory[A, Iterable[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Iterable[A], Any] = immutable.Iterable.newBuilder[A] + + def fromOld[A](it: scala.Iterable[A]): Iterable[A] = new Iterable[A] { + def elements: Iterator[A] = Iterator.fromOld(it.elements) + } + + def toOld[A](it: Iterable[A]): scala.Iterable[A] = new scala.Iterable[A] { + def elements: scala.Iterator[A] = Iterator.toOld(it.elements) + } + + /** The minimum element of a non-empty sequence of ordered elements + * @deprecated use seq.min instead + */ + @deprecated def min[A <% Ordered[A]](seq: Iterable[A]): A = { + val xs = seq.elements + if (!xs.hasNext) throw new IllegalArgumentException("min(<empty>)") + var min = xs.next + while (xs.hasNext) { + val x = xs.next + if (x < min) min = x + } + min + } + + /** The maximum element of a non-empty sequence of ordered elements + * @deprecated use seq.max iConstead + */ + @deprecated def max[A <% Ordered[A]](seq: Iterable[A]): A = { + val xs = seq.elements + if (!xs.hasNext) throw new IllegalArgumentException("max(<empty>)") + var max = xs.next + while (xs.hasNext) { + val x = xs.next + if (max < x) max = x + } + max + } + + /** @deprecated use View instead + */ + @deprecated type Projection[A] = IterableView[A, Coll] +} diff --git a/src/library/scala/collection/immutable/EmptySet.scala b/src/library/scala/collection/IterableProxy.scala index b687b92788..6bb12e84dc 100644 --- a/src/library/scala/collection/immutable/EmptySet.scala +++ b/src/library/scala/collection/IterableProxy.scala @@ -6,31 +6,20 @@ ** |/ ** \* */ -// $Id$ +// $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ +package scala.collection -package scala.collection.immutable - -/** This class implements empty immutable sets - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class EmptySet[A] extends Set[A] { - - def empty[C]: Set[C] = new EmptySet[C] - - def size: Int = 0 - - def contains(elem: A): Boolean = false - - def + (elem: A): Set[A] = new Set1(elem) - - def - (elem: A): Set[A] = this - - def elements: Iterator[A] = Iterator.empty -} +import generic._ +// Methods could be printed by cat Traversibe.scala | egrep '^ (override )?def' +/** This trait implements a proxy for iterable objects. It forwards + * all calls to a different iterable object + * + * @author Martin Odersky + * @version 2.8 + */ +trait IterableProxy[+A] extends Iterable[A] with IterableProxyTemplate[A, Iterable[A]] diff --git a/src/library/scalax/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 48eda407aa..1853571e21 100755 --- a/src/library/scalax/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -9,10 +9,10 @@ // $Id: Iterator.scala 15939 2008-08-26 14:33:17Z stepancheg $ -package scalax.collection +package scala.collection import mutable.{Buffer, ArrayBuffer, ListBuffer} -import immutable.{List, Nil, ::, Stream} +// import immutable.{List, Nil, ::, Stream} /** The <code>Iterator</code> object provides various functions for * creating specialized iterators. @@ -23,15 +23,24 @@ import immutable.{List, Nil, ::, Stream} */ object Iterator { + def fromOld[A](it: scala.Iterator[A]): Iterator[A] = new Iterator[A] { + def hasNext: Boolean = it.hasNext + def next: A = it.next + } + + def toOld[A](it: Iterator[A]): scala.Iterator[A] = new scala.Iterator[A] { + def hasNext: Boolean = it.hasNext + def next: A = it.next + } + val empty = new Iterator[Nothing] { def hasNext: Boolean = false def next(): Nothing = throw new NoSuchElementException("next on empty iterator") } - /** + /** An iterator with a single element. * @param elem the element - * @return the iterator with one single element - * @note Equivalent, but more efficient than Iterator(x) + * @note Equivalent, but more efficient than Iterator(elem) */ def single[A](elem: A) = new Iterator[A] { private var hasnext = true @@ -41,21 +50,24 @@ object Iterator { else empty.next() } - def apply[A](args: A*): Iterator[A] = args.asInstanceOf[Iterable[A]].elements // !@! + /** Creates an iterator with given elements + * @param elems The elements returned one-by-one from the iterator + */ + def apply[A](elems: A*): Iterator[A] = Iterable.fromOld(elems).elements - /** Concatenate all the argument iterators into a single iterator. + /** Concatenates the given argument iterators into a single iterator. * - * @param xss the lists that are to be concatenated - * @return the concatenation of all the lists + * @param its the argument iterators that are to be concatenated + * @return the concatenation of all the argument iterators */ def concat[A](xss: Iterator[A]*): Iterator[A] = - xss.asInstanceOf[Iterable[Iterator[A]]].elements.flatten // !@! + Iterable.fromOld(xss).elements.flatten - /** An iterator that returns the same element a number of times + /** An iterator that returns the results of some element computation a number of times. * @param len The number of elements returned - * @param elem The element returned each time + * @param elem The element computation determinining each result */ - def fill[A](len: Int, elem: => A) = new Iterator[A] { + def fill[A](len: Int)(elem: => A) = new Iterator[A] { private var i = 0 def hasNext: Boolean = i < len def next(): A = @@ -63,41 +75,36 @@ object Iterator { else empty.next() } - /** An iterator that returns values of a function <code>f(0), ..., f(n-1)</code>, - * for given `f` and `n`. + /** An iterator that returns values of a given function over a range of integer values starting from 0. + * @param end The argument up to which values are tabulated. + * @param f The function computing the results + * @return An iterator with values `f(0) ... f(end-1)` */ - def tabulate[A](n: Int)(f: Int => A) = new Iterator[A] { + def tabulate[A](end: Int)(f: Int => A) = new Iterator[A] { private var i = 0 - def hasNext: Boolean = i < n + def hasNext: Boolean = i < end def next(): A = if (hasNext) { val result = f(i); i += 1; result } else empty.next() } - /** Nn iterator with elements - * <code>e<sub>n+1</sub> = e<sub>n</sub> + 1</code> - * where <code>e<sub>0</sub> = start</code> - * and <code>e<sub>i</sub> < end</code>. However, - * if <code>start ≥ end</code>, then it will return an empty range. + /** An iterator returning successive values in some integer interval. * * @param start the start value of the iterator - * @param end the end value of the iterator - * @return the iterator with values in range <code>[start;end)</code>. + * @param end the end value of the iterator (the first value NOT returned) + * @return the iterator with values in range `start, start + 1, ..., end - 1` */ def range(start: Int, end: Int): Iterator[Int] = range(start, end, 1) - /** Create an iterator with elements - * <code>e<sub>n+1</sub> = e<sub>n</sub> + step</code> - * where <code>e<sub>0</sub> = start</code> - * and elements are in the range between <code>start</code> (inclusive) - * and <code>end</code> (exclusive) - * + /** An iterator returning equally spaced values in some integer interval. + * @param start the start value of the iterator - * @param end the end value of the iterator + * @param end the end value of the iterator (the first value NOT returned) * @param step the increment value of the iterator (must be positive or negative) - * @return the iterator with values in range <code>[start;end)</code>. + * @return the iterator with values in `start, start + step, ...` up to, but excluding `end` */ def range(start: Int, end: Int, step: Int) = new Iterator[Int] { + if (step == 0) throw new IllegalArgumentException("zero step") private var i = start def hasNext: Boolean = (step <= 0 || i < end) && (step >= 0 || i > end) def next(): Int = @@ -107,10 +114,10 @@ object Iterator { /** An iterator that repeatedly applies a given function to a start value. * - * @param start the start value of the iteratpr + * @param start the start value of the iterator * @param len the number of elements returned by the iterator * @param f the function that's repeatedly applied - * @return the iterator returning values <code>(start, f(start), f(f(start)), ..., f<sup>len-1</sup>(start))</code> + * @return the iterator returning `len` values in the sequence `start, f(start), f(f(start)), ...` */ def iterate(start: Int, len: Int)(f: Int => Int) = new Iterator[Int] { private var acc = start @@ -123,9 +130,9 @@ object Iterator { /** An infinite iterator that repeatedly applies a given function to a start value. * - * @param start the start value of the iteratpr + * @param start the start value of the iterator * @param f the function that's repeatedly applied - * @return the iterator returning values <code>(start, f(start), f(f(start)), ..., f<sup>len-1</sup>(start))</code> + * @return the iterator returning the infinite sequence of values `start, f(start), f(f(start)), ...` */ def iterate(start: Int)(f: Int => Int) = new Iterator[Int] { private var acc = start @@ -134,48 +141,44 @@ object Iterator { def next(): Int = { val result = f(acc); i += 1; result } } - /** Create an iterator with elements - * <code>e<sub>n+1</sub> = e<sub>n</sub> + 1</code> - * where <code>e<sub>0</sub> = start</code>. - * + /** An infinite-length iterator which returns successive values from some start value. + * @param start the start value of the iterator - * @return the iterator starting at value <code>start</code>. + * @return the iterator returning the infinite sequence of values `start, start + 1, start + 2, ...` */ def from(start: Int): Iterator[Int] = from(start, 1) - /** Create an iterator with elements - * <code>e<sub>n+1</sub> = e<sub>n</sub> + step</code> - * where <code>e<sub>0</sub> = start</code>. + /** An infinite-length iterator returning values equally spaced apart. * * @param start the start value of the iterator - * @param step the increment value of the iterator - * @return the iterator starting at value <code>start</code>. + * @param step the increment between successive values + * @return the iterator returning the infinite sequence of values `start, start + 1 * step, start + 2 * step, ...` */ def from(start: Int, step: Int): Iterator[Int] = new Iterator[Int] { - private var i = 0 + private var i = start def hasNext: Boolean = true - def next(): Int = { val result = i; i += 1; result } + def next(): Int = { val result = i; i += step; result } } + /** A wrapper class for the `flatten `method that is added to class Iterator with implicit conversion @see iteratorIteratorWrapper. + */ class IteratorIteratorOps[A](its: Iterator[Iterator[A]]) { - /** Create an iterator that is the concantenation of all iterators - * returned by a given iterator of iterators. - * @param its The iterator which returns on each call to next - * a new iterator whose elements are to be concatenated to the result. + /** If `its` is an iterator of iterators, `its.flatten` gives the iterator that is the concatenation of all iterators in `its`. */ def flatten: Iterator[A] = new Iterator[A] { - private var it = its.next - def hasNext: Boolean = if (it.hasNext) { it = its.next; hasNext } else false - def next(): A = if (hasNext) it.next else empty.next() + private var it: Iterator[A] = empty + def hasNext: Boolean = it.hasNext || its.hasNext && { it = its.next(); hasNext } + def next(): A = if (hasNext) it.next() else empty.next() } } + /** An implicit conversion which adds the `flatten` method to class `Iterator` */ implicit def iteratorIteratorWrapper[A](its: Iterator[Iterator[A]]): IteratorIteratorOps[A] = new IteratorIteratorOps[A](its) - /** @deprecated use `xs.elements`, or `Iterator(x1, ..., xn)` instead + /** @deprecated use `xs.elements` instead */ - @deprecated def fromValues[a](xs: a*) = xs.elements + @deprecated def fromValues[a](xs: a*) = Iterable.fromOld(xs).elements /** * @param xs the array of elements @@ -193,7 +196,7 @@ object Iterator { * @deprecated use `xs.slice(start, start + length).elements` instead */ @deprecated def fromArray[a](xs: Array[a], start: Int, length: Int): Iterator[a] = - xs.slice(start, start + length).elements.asInstanceOf[Iterator[a]] // !@! + Iterable.fromOld(xs.slice(start, start + length)).elements /** * @param str the given string @@ -201,7 +204,7 @@ object Iterator { * @deprecated replaced by <code>str.elements</code> */ @deprecated def fromString(str: String): Iterator[Char] = - str.elements.asInstanceOf[Iterator[Char]] // !@! + Iterable.fromOld(str).elements /** * @param n the product arity @@ -259,14 +262,13 @@ object Iterator { * @deprecated use its.flatten instead */ @deprecated def flatten[T](its: Iterator[Iterator[T]]): Iterator[T] = new Iterator[T] { - private var it = its.next + private var cur = its.next def hasNext: Boolean = { - while (!it.hasNext && its.hasNext) it = its.next - it.hasNext + while (!cur.hasNext && its.hasNext) cur = its.next + cur.hasNext } def next(): T = - if (hasNext) it.next - else empty.next() + (if (hasNext) cur else empty).next() } } @@ -280,19 +282,18 @@ import Iterator.empty * @author Martin Odersky, Matthias Zenger * @version 2.8 */ -trait Iterator[+A] { -self => +trait Iterator[+A] { self => /** Does this iterator provide another element? */ def hasNext: Boolean - /** Returns the next element. + /** Returns the next element of this iterator. */ def next(): A /** Returns a new iterator that iterates only over the first <code>n</code> - * elements. + * elements of this iterator, or the length of the iterator, whichever is smaller. * * @param n the number of elements to take * @return the new iterator @@ -302,19 +303,19 @@ self => def hasNext = remaining > 0 && self.hasNext def next(): A = if (hasNext) { remaining -= 1; self.next } - else throw new NoSuchElementException("next on empty iterator") + else empty.next() } - /** Removes the first <code>n</code> elements from this iterator. - * + /** Advances this iterator past the first <code>n</code> elements, + * or the length of the iterator, whichever is smaller. * @param n the number of elements to drop * @return the new iterator */ def drop(n: Int): Iterator[A] = if (n > 0 && hasNext) { next(); drop(n - 1) } else this - /** A sub-iterator of <code>until - from elements - * starting at index <code>from</code> + /** Advances this iterator past the first `from` elements using `drop`, + * and then takes `until - from` elements, using `take`. * * @param from The index of the first element of the slice * @param until The index of the element following the slice @@ -331,21 +332,12 @@ self => /** Returns a new iterator that first yields the elements of this * iterator followed by the elements provided by iterator <code>that</code>. - * @deprecated use <code>++</code> - */ - def append[B >: A](that: Iterator[B]) = new Iterator[B] { - def hasNext = self.hasNext || that.hasNext - def next() = (if (self.hasNext) self else that).next() - } - - /** Returns a new iterator that first yields the elements of this - * iterator followed by the elements provided by iterator <code>that</code>. */ def ++[B >: A](that: => Iterator[B]) = new Iterator[B] { // optimize a little bit to prevent n log n behavior. var cur : Iterator[B] = self def hasNext = cur.hasNext || (cur eq self) && { cur = that; hasNext } - def next() = { hasNext; cur.next } + def next() = { hasNext; cur.next() } } /** Applies the given function <code>f</code> to each element of @@ -383,8 +375,6 @@ self => * all elements of the result satisfy the predicate <code>p</code>. * The order of the elements is preserved. * - * The behavior of <code>this</code> iterator is undefined after this method invocation. - * * @param p the predicate used to filter the iterator. * @return the longest prefix of this iterator satisfying <code>p</code>. */ @@ -413,8 +403,9 @@ self => while (self.hasNext && !p(self.head)) { other.lookahead += self.next } - def hasNext = !lookahead.isEmpty || self.hasNext - def next() = if (lookahead.isEmpty) self.next() else lookahead.dequeue() + def hasNext = !lookahead.isEmpty || { skip(); self.hasNext } + def next() = if (!lookahead.isEmpty) lookahead.dequeue() + else { skip(); self.next() } } val l = new PartitionIterator(p) val r = new PartitionIterator(!p(_)) @@ -426,8 +417,6 @@ self => /** Skips longest sequence of elements of this iterator which satisfy given * predicate <code>p</code>, and returns an iterator of the remaining elements. * - * The behavior of <code>this</code> iterator is undefined after this method invocation. - * * @param p the predicate used to skip elements. * @return an iterator consisting of the remaining elements */ @@ -450,23 +439,30 @@ self => * the element at the same position in the latter. * If one of the two iterators is longer than the other, its remaining elements are ignored. * - * @return an iterator yielding <code>{a<sub>0</sub>,b<sub>0</sub>}, - * {a<sub>1</sub>,b<sub>1</sub>}, ...</code> where - * <code>a<sub>i</sub></code> are the elements from this iterator - * and <code>b<sub>i</sub></code> are the elements from iterator - * <code>that</code>. */ def zip[B](that: Iterator[B]) = new Iterator[(A, B)] { def hasNext = self.hasNext && that.hasNext def next = (self.next, that.next) } + /** Return a new iterator with a length equal or longer to `len`. + * If the current iterator returns fewer than `len` elements + * return `elem` until the required length `len` is reached. + */ + def padTo[A1 >: A](len: Int, elem: A1) = new Iterator[A1] { + private var count = 0 + def hasNext = self.hasNext || count < len + def next = { + count += 1 + if (self.hasNext) self.next + else if (count <= len) elem + else empty.next + } + } + /** Return an iterator that pairs each element of this iterator * with its index, counting from 0. * - * @return an iterator yielding <code>{a<sub>0</sub>,0}, - * {a<sub>1</sub>,1}...</code> where <code>a<sub>i</sub></code> - * are the elements from this iterator. */ def zipWithIndex = new Iterator[(A, Int)] { var idx = 0 @@ -509,8 +505,8 @@ self => } } - /** Apply a function <code>f</code> to all elements of this - * iterable object. + /** Execute a function <code>f</code> for all elements of this + * iterator. * * @param f a function that is applied to every element. */ @@ -531,7 +527,7 @@ self => } /** Apply a predicate <code>p</code> to all elements of this - * iterable object and return true, iff there is at least one + * iterable object and return true iff there is at least one * element for which <code>p</code> yields <code>true</code>. * * @param p the predicate @@ -544,15 +540,13 @@ self => res } - /** Tests if the given value <code>elem</code> is a member of this iterator. + /** Tests if the given value <code>elem</code> is a member of this iterator. * * @param elem element whose membership has to be tested. - * @return <code>true</code> iff there is an element of this iterator which - * is equal (w.r.t. <code>==</code>) to <code>elem</code>. */ - def contains(elem: Any): Boolean = exists { _ == elem } + def contains(elem: Any): Boolean = exists(_ == elem) - /** Find and return the first element of the iterable object satisfying a + /** Find and return the first value returned by the iterator satisfying a * predicate, if any. * * @param p the predicate @@ -568,7 +562,7 @@ self => res } - /** Returns index of the first element satisying a predicate, or -1. + /** Returns index of the first element satisfying a predicate, or -1. * * @note may not terminate for infinite-sized collections. * @param p the predicate @@ -588,12 +582,6 @@ self => if (found) i else -1 } - /** Returns index of the first element satisying a predicate, or -1. - * - * @deprecated use `indexWhere` instead - */ - @deprecated def findIndexOf(p: A => Boolean): Int = indexWhere(p) - /** Returns the index of the first occurence of the specified * object in this iterable object. * @@ -638,10 +626,8 @@ self => * if the iterator yields elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., * a<sub>n</sub></code>. */ - def foldRight[B](z: B)(op: (A, B) => B): B = { - def fold(z: B): B = if (hasNext) op(next(), fold(z)) else z - fold(z) - } + def foldRight[B](z: B)(op: (A, B) => B): B = + if (hasNext) op(next(), foldRight(z)(op)) else z /** Similar to <code>foldLeft</code> but can be used as * an operator with the order of iterator and zero arguments reversed. @@ -690,8 +676,26 @@ self => * @throws Predef.UnsupportedOperationException if the iterator is empty. */ def reduceRight[B >: A](op: (A, B) => B): B = { - if (!hasNext) throw new UnsupportedOperationException("empty.reduceRight") - foldRight[B](next())(op) + if (hasNext) foldRight[B](next())(op) + else throw new UnsupportedOperationException("empty.reduceRight") + } + + /** Combines the elements of this iterator together using the binary + * operator <code>op</code>, from left to right + * @param op The operator to apply + * @return If the iterable is non-empty, the result of the operations as an Option, otherwise None. + */ + def reduceLeftOpt[B >: A](op: (B, A) => B): Option[B] = { + if (!hasNext) None else Some(reduceLeft(op)) + } + + /** Combines the elements of this iterable object together using the binary + * operator <code>op</code>, from right to left. + * @param op The operator to apply + * @return If the iterable is non-empty, the result of the operations as an Option, otherwise None. + */ + def reduceRightOpt[B >: A](op: (A, B) => B): Option[B] = { + if (!hasNext) None else Some(reduceRight(op)) } /** Returns a buffered iterator from this iterator. @@ -718,6 +722,9 @@ self => } else self.next } + /** Returns the number of elements in this iterator. + * @note The iterator is at its end after this method returns. + */ def length: Int = { var i = 0 while (hasNext) { @@ -726,65 +733,44 @@ self => i } - /** Returns a counted iterator from this iterator. - * @deprecated use @see zipWithIndex in Iterator - */ - def counted = new CountedIterator[A] { - private var cnt = -1 - def count = cnt - def hasNext: Boolean = self.hasNext - def next(): A = { cnt += 1; self.next } - } - /** Creates two new iterators that both iterate over the same elements - * than this iterator (in the same order). + * as this iterator (in the same order). * * @return a pair of iterators */ def duplicate: (Iterator[A], Iterator[A]) = { - var xs: List[A] = Nil + val gap = new scala.collection.mutable.Queue[A] var ahead: Iterator[A] = null class Partner extends Iterator[A] { - var ys: List[A] = Nil - def hasNext: Boolean = self.synchronized ( - ((this == ahead) && self.hasNext) || - ((this != ahead) && (!xs.isEmpty || !ys.isEmpty || self.hasNext)) - ) + def hasNext: Boolean = self.synchronized { + (this ne ahead) && !gap.isEmpty || self.hasNext + } def next(): A = self.synchronized { - if (this == ahead) { + if (gap.isEmpty) ahead = this + if (this eq ahead) { val e = self.next() - xs = e :: xs; e - } else { - if (ys.isEmpty) { - ys = xs.reverse - xs = Nil - } - ys match { - case Nil => - val e = self.next() - ahead = this - xs = e :: xs; e - case z :: zs => - ys = zs; z - } - } + gap enqueue e + e + } else gap.dequeue } } - ahead = new Partner - (ahead, new Partner) + (new Partner, new Partner) } - def patch[B >: A](from: Int, ps: Sequence[B], replaced: Int) = new Iterator[B] { - private val plen = ps.length + /** Returns this iterator with patched values. + * @param from The start index from which to patch + * @param ps The iterator of patch values + * @param replaced The number of values in the original iterator that are replaced by the patch. + */ + def patch[B >: A](from: Int, patchElems: Iterator[B], replaced: Int) = new Iterator[B] { private var origElems = self - private val patchElems = ps.elements private var i = 0 def hasNext: Boolean = if (i < from) origElems.hasNext else patchElems.hasNext || origElems.hasNext def next(): B = { val result: B = - if (i < from || i >= from + plen) origElems.next() + if (i < from || !patchElems.hasNext) origElems.next() else patchElems.next() i += 1 if (i == from) origElems = origElems drop replaced @@ -792,19 +778,17 @@ self => } } - /** Fills the given array <code>xs</code> with at most `len` elements of - * this iterator starting at position `start`. - * Copying will stop once either the end of the current iterable is reached or - * `len` elements have been copied. + /** Fills the given array `xs` with at most `len` elements of + * this iterator starting at position `start` until either `len` elements have been copied, + * or the end of the iterator is reached, or the end of the array `xs` is reached. * * @param xs the array to fill. * @param start starting index. * @param len number of elements to copy - * @pre the array must be large enough to hold all elements. */ def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Unit = { var i = start - val end = start + len + val end = start + len min xs.length while (hasNext && i < end) { xs(i) = next() i += 1 @@ -817,7 +801,6 @@ self => * * @param xs the array to fill. * @param start starting index. - * @pre the array must be large enough to hold all elements. */ def copyToArray[B >: A](xs: Array[B], start: Int): Unit = copyToArray(xs, start, xs.length - start) @@ -827,44 +810,19 @@ self => * until either the end of the current iterator or the end of array `xs` is reached. * * @param xs the array to fill. - * @pre the array must be large enough to hold all elements. */ def copyToArray[B >: A](xs: Array[B]): Unit = copyToArray(xs, 0, xs.length) - /** Fills the given array <code>xs</code> with the elements of - * this sequence starting at position <code>start</code>. Like <code>copyToArray</code>, - * but designed to accomodate IO stream operations. - * - * @param xs the array to fill. - * @param start the starting index. - * @param sz the maximum number of elements to be read. - * @pre the array must be large enough to hold <code>sz</code> elements. - * @deprecated use copyToArray instead - */ - @deprecated def readInto[B >: A](xs: Array[B], start: Int, sz: Int) { - var i = start - while (hasNext && i - start < sz) { - xs(i) = next - i += 1 - } - } - @deprecated def readInto[B >: A](xs: Array[B], start: Int) { - readInto(xs, start, xs.length - start) - } - @deprecated def readInto[B >: A](xs: Array[B]) { - readInto(xs, 0, xs.length) - } - /** Copy all elements to a buffer - * @param The buffer to which elements are copied + * @param dest The buffer to which elements are copied */ def copyToBuffer[B >: A](dest: Buffer[B]) { while (hasNext) dest += next } - /** Transform this iterator into a list of all elements. + /** Traverse this iterator and return all elements in a list. * - * @return a list which enumerates all elements of this iterator. + * @return A list which enumerates all elements of this iterator. */ def toList: List[A] = { val res = new ListBuffer[A] @@ -872,32 +830,27 @@ self => res.toList } - /** - * Create a stream which contains all the elements of this iterator. + /** Traverse this iterator and return all elements in a stream. + * + * @return A stream which enumerates all elements of this iterator. */ def toStream: Stream[A] = if (hasNext) Stream.cons(next, toStream) else Stream.empty - /** - * Create a sequence which contains all the elements of this iterator. + /** Traverse this iterator and return all elements in a sequence. + * + * @return A sequence which enumerates all elements of this iterator. */ def toSequence: Sequence[A] = { val buffer = new ArrayBuffer[A] this copyToBuffer buffer - buffer.readOnly + buffer } - /** Collect elements into a seq. - * - * @return a sequence which enumerates all elements of this iterator. - * @deprecated use toSequence instead - */ - @deprecated def collect: Sequence[A] = toSequence - /** Returns a string representation of the elements in this iterator. The resulting string * begins with the string <code>start</code> and is finished by the string * <code>end</code>. Inside, the string representations of elements (w.r.t. - * the method <code>toString()</code>) are separated by the string + * the method <code>toString</code>) are separated by the string * <code>sep</code>. * <p/> * Ex: <br/> @@ -920,16 +873,15 @@ self => * @param sep separator string. * @return a string representation of this iterable object. */ - def mkString(sep: String): String = this.mkString("", sep, "") + def mkString(sep: String): String = mkString("", sep, "") /** Returns a string representation of this iterable object. The string * representations of elements (w.r.t. the method <code>toString()</code>) - * are separated by a comma. + * are concatenated without any separator string. * * @return a string representation of this iterable object. */ - def mkString: String = - mkString("") + def mkString: String = mkString("") /** Write all elements of this iterator into given string builder. * The written text begins with the string <code>start</code> and is finished by the string @@ -951,15 +903,68 @@ self => * The string representations of elements (w.r.t. the method <code>toString()</code>) * are separated by the string <code>sep</code>. */ - def addString(buf: StringBuilder, sep: String): StringBuilder = - addString(buf, "", sep, "") + def addString(buf: StringBuilder, sep: String): StringBuilder = addString(buf, "", sep, "") /** Write all elements of this string into given string builder without using * any separator between consecutive elements. */ - def addString(buf: StringBuilder): StringBuilder = - addString(buf, "", "", "") + def addString(buf: StringBuilder): StringBuilder = addString(buf, "", "", "") override def toString = (if (hasNext) "non-empty" else "empty")+" iterator" + /** Returns a new iterator that first yields the elements of this + * iterator followed by the elements provided by iterator <code>that</code>. + * @deprecated use <code>++</code> + */ + @deprecated def append[B >: A](that: Iterator[B]) = new Iterator[B] { + def hasNext = self.hasNext || that.hasNext + def next() = (if (self.hasNext) self else that).next() + } + + /** Returns index of the first element satisfying a predicate, or -1. + * + * @deprecated use `indexWhere` instead + */ + @deprecated def findIndexOf(p: A => Boolean): Int = indexWhere(p) + + /** Collect elements into a seq. + * + * @return a sequence which enumerates all elements of this iterator. + * @deprecated use toSequence instead + */ + @deprecated def collect: Sequence[A] = toSequence + + /** Returns a counted iterator from this iterator. + * @deprecated use @see zipWithIndex in Iterator + */ + @deprecated def counted = new CountedIterator[A] { + private var cnt = -1 + def count = cnt + def hasNext: Boolean = self.hasNext + def next(): A = { cnt += 1; self.next } + } + + /** Fills the given array <code>xs</code> with the elements of + * this sequence starting at position <code>start</code>. Like <code>copyToArray</code>, + * but designed to accomodate IO stream operations. + * + * @param xs the array to fill. + * @param start the starting index. + * @param sz the maximum number of elements to be read. + * @pre the array must be large enough to hold <code>sz</code> elements. + * @deprecated use copyToArray instead + */ + @deprecated def readInto[B >: A](xs: Array[B], start: Int, sz: Int) { + var i = start + while (hasNext && i - start < sz) { + xs(i) = next + i += 1 + } + } + @deprecated def readInto[B >: A](xs: Array[B], start: Int) { + readInto(xs, start, xs.length - start) + } + @deprecated def readInto[B >: A](xs: Array[B]) { + readInto(xs, 0, xs.length) + } } diff --git a/src/library/scala/collection/JavaConversions.scala b/src/library/scala/collection/JavaConversions.scala new file mode 100644 index 0000000000..d28959d857 --- /dev/null +++ b/src/library/scala/collection/JavaConversions.scala @@ -0,0 +1,484 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection + +/** + * A collection of implicit conversions supporting interoperability between Scala and Java + * collections. + * <p> + * The following conversions are supported, + * <p> + * <ul> + * <li><code>scala.collection.Iterable</code> <=> <code>java.lang.Iterable</code></li> + * <li><code>scala.collection.Iterable</code> <=> <code>java.util.Collection</code></li> + * <li><code>scala.collection.Iterator</code> <=> <code>java.util.{ Iterator, Enumeration }</code></li> + * <li<code>>scala.collection.mutable.Buffer</code> <=> <code>java.util.List</code></li> + * <li<code>>scala.collection.mutable.Set</code> <=> <code>java.util.Set</code></li> + * <li<code>>scala.collection.mutable.Map</code> <=> <code>java.util.Map</code></li> + * <ul> + * <p> + * In all cases, converting from a source type to a target type and back again will return + * the original source object, eg. + * <p> + * <pre> + * import scala.collections.jcl.Conversions._ + * + * val sl = new scala.collection.mutable.ListBuffer[Int] + * val jl : java.util.List[Int] = sl + * val sl2 : scala.collection.mutable.Buffer[Int] = jl + * assert(sl eq sl2)g + * </pre> + * + * <p> + * Note that no conversion is provided from scala.collection.immutable.List to java.util.List. + * Instead it is convertible to an immutable java.util.Collection which provides size and + * interation capabilities, but not access by index as would be provided by java.util.List. + * This is intentional: in combination the implementation of scala.collection.immutable.List + * and the typical usage patterns of java.util.List would perform extremely poorly. + * + * @author Miles Sabin + */ +object JavaConversions { + import java.{ lang => jl, util => ju } + import scala.collection.{ generic, immutable, mutable, Traversible } + import scala.reflect.Manifest + + // Scala => Java + + /** + * Implicitly converts a Scala <code>Iterator</code> to a Java <code>Iterator</code>. + * The returned Java <code>Iterator</code> is backed by the provided Scala + * <code>Iterator</code> and any side-effects of using it via the Java interface will + * be visible via the Scala interface and vice versa. + * <p> + * If the Scala <code>Iterator</code> was previously obtained from an implicit or + * explicit call of <code>asIterator(java.util.Iterator)</code> then the original + * Java <code>Iterator</code> will be returned. + * + * @param i The <code>Iterator</code> to be converted. + * @return A Java <code>Iterator</code> view of the argument. + */ + implicit def asIterator[A](i : Iterator[A]) = i match { + case JIteratorWrapper(wrapped) => wrapped + case _ => IteratorWrapper(i) + } + + /** + * Implicitly converts a Scala <code>Iterator</code> to a Java <code>Enumeration</code>. + * The returned Java <code>Enumeration</code> is backed by the provided Scala + * <code>Iterator</code> and any side-effects of using it via the Java interface will + * be visible via the Scala interface and vice versa. + * <p> + * If the Scala <code>Iterator</code> was previously obtained from an implicit or + * explicit call of <code>asIterator(java.util.Enumeration)</code> then the + * original Java <code>Enumeration</code> will be returned. + * + * @param i The <code>Iterator</code> to be converted. + * @return A Java <code>Enumeration</code> view of the argument. + */ + implicit def asEnumeration[A](i : Iterator[A]) = i match { + case JEnumerationWrapper(wrapped) => wrapped + case _ => IteratorWrapper(i) + } + + /** + * Implicitly converts a Scala <code>Iterable</code> to a Java <code>Iterable</code>. + * The returned Java <code>Iterable</code> is backed by the provided Scala + * <code>Iterable</code> and any side-effects of using it via the Java interface will + * be visible via the Scala interface and vice versa. + * <p> + * If the Scala <code>Iterable</code> was previously obtained from an implicit or + * explicit call of <code>asIterable(java.lang.Iterable)</code> then the original + * Java <code>Iterable</code> will be returned. + * + * @param i The <code>Iterable</code> to be converted. + * @return A Java <code>Iterable</code> view of the argument. + */ + implicit def asIterable[A](i : Iterable[A]) = i match { + case JIterableWrapper(wrapped) => wrapped + case _ => IterableWrapper(i) + } + + /** + * Implicitly converts a Scala <code>Iterable</code> to an immutable Java + * <code>Collection</code>. + * <p> + * If the Scala <code>Iterable</code> was previously obtained from an implicit or + * explicit call of <code>asSizedIterable(java.util.Collection)</code> then the original + * Java <code>Collection</code> will be returned. + * + * @param i The <code>SizedIterable</code> to be converted. + * @return A Java <code>Collection</code> view of the argument. + */ + implicit def asCollection[A](i : Iterable[A]) = i match { + case JCollectionWrapper(wrapped) => wrapped + case _ => new IterableWrapper(i) + } + + /** + * Implicitly converts a Scala mutable <code>Buffer</code> to a Java <code>List</code>. + * The returned Java <code>List</code> is backed by the provided Scala + * <code>Buffer</code> and any side-effects of using it via the Java interface will + * be visible via the Scala interface and vice versa. + * <p> + * If the Scala <code>Buffer</code> was previously obtained from an implicit or + * explicit call of <code>asBuffer(java.util.List)</code> then the original + * Java <code>List</code> will be returned. + * + * @param b The <code>Buffer</code> to be converted. + * @return A Java <code>List</code> view of the argument. + */ + implicit def asList[A](b : mutable.Buffer[A]) : ju.List[A] = b match { + case JListWrapper(wrapped) => wrapped + case _ => new MutableBufferWrapper(b) + } + + /** + * Implicitly converts a Scala mutable <code>Set</code> to a Java <code>Set</code>. + * The returned Java <code>Set</code> is backed by the provided Scala + * <code>Set</code> and any side-effects of using it via the Java interface will + * be visible via the Scala interface and vice versa. + * <p> + * If the Scala <code>Set</code> was previously obtained from an implicit or + * explicit call of <code>asSet(java.util.Set)</code> then the original + * Java <code>Set</code> will be returned. + * + * @param s The <code>Set</code> to be converted. + * @return A Java <code>Set</code> view of the argument. + */ + implicit def asSet[A](s : mutable.Set[A])(implicit m : Manifest[A]) : ju.Set[A] = s match { + case JSetWrapper(wrapped) => wrapped + case _ => new MutableSetWrapper(s)(m) + } + + /** + * Implicitly converts a Scala mutable <code>Map</code> to a Java <code>Map</code>. + * The returned Java <code>Map</code> is backed by the provided Scala + * <code>Map</code> and any side-effects of using it via the Java interface will + * be visible via the Scala interface and vice versa. + * <p> + * If the Scala <code>Map</code> was previously obtained from an implicit or + * explicit call of <code>asMap(java.util.Map)</code> then the original + * Java <code>Map</code> will be returned. + * + * @param m The <code>Map</code> to be converted. + * @return A Java <code>Map</code> view of the argument. + */ + implicit def asMap[A, B](m : mutable.Map[A, B])(implicit ma : Manifest[A]) : ju.Map[A, B] = m match { + case JMapWrapper(wrapped) => wrapped + case _ => new MutableMapWrapper(m)(ma) + } + + // Java => Scala + + /** + * Implicitly converts a Java <code>Iterator</code> to a Scala <code>Iterator</code>. + * The returned Scala <code>Iterator</code> is backed by the provided Java + * <code>Iterator</code> and any side-effects of using it via the Scala interface will + * be visible via the Java interface and vice versa. + * <p> + * If the Java <code>Iterator</code> was previously obtained from an implicit or + * explicit call of <code>asIterator(scala.collection.Iterator)</code> then the original + * Scala <code>Iterator</code> will be returned. + * + * @param i The <code>Iterator</code> to be converted. + * @return A Scala <code>Iterator</code> view of the argument. + */ + implicit def asIterator[A](i : ju.Iterator[A]) = i match { + case IteratorWrapper(wrapped) => wrapped + case _ => JIteratorWrapper(i) + } + + /** + * Implicitly converts a Java <code>Enumeration</code> to a Scala <code>Iterator</code>. + * The returned Scala <code>Iterator</code> is backed by the provided Java + * <code>Enumeration</code> and any side-effects of using it via the Scala interface will + * be visible via the Java interface and vice versa. + * <p> + * If the Java <code>Enumeration</code> was previously obtained from an implicit or + * explicit call of <code>asEnumeration(scala.collection.Iterator)</code> then the + * original Scala <code>Iterator</code> will be returned. + * + * @param i The <code>Enumeration</code> to be converted. + * @return A Scala <code>Iterator</code> view of the argument. + */ + implicit def asIterator[A](i : ju.Enumeration[A]) = i match { + case IteratorWrapper(wrapped) => wrapped + case _ => JEnumerationWrapper(i) + } + + /** + * Implicitly converts a Java <code>Iterable</code> to a Scala <code>Iterable</code>. + * The returned Scala <code>Iterable</code> is backed by the provided Java + * <code>Iterable</code> and any side-effects of using it via the Scala interface will + * be visible via the Java interface and vice versa. + * <p> + * If the Java <code>Iterable</code> was previously obtained from an implicit or + * explicit call of <code>asIterable(scala.collection.Iterable)</code> then the original + * Scala <code>Iterable</code> will be returned. + * + * @param i The <code>Iterable</code> to be converted. + * @return A Scala <code>Iterable</code> view of the argument. + */ + implicit def asIterable[A](i : jl.Iterable[A]) = i match { + case IterableWrapper(wrapped) => wrapped + case _ => JIterableWrapper(i) + } + + /** + * Implicitly converts a Java <code>Collection</code> to an Scala <code>Iterable</code>. + * <p> + * If the Java <code>Collection</code> was previously obtained from an implicit or + * explicit call of <code>asCollection(scala.collection.SizedIterable)</code> then + * the original Scala <code>SizedIterable</code> will be returned. + * + * @param i The <code>Collection</code> to be converted. + * @return A Scala <code>SizedIterable</code> view of the argument. + */ + implicit def asIterable[A](i : ju.Collection[A]) = i match { + case IterableWrapper(wrapped) => wrapped + case _ => JCollectionWrapper(i) + } + + /** + * Implicitly converts a Java <code>List</code> to a Scala mutable <code>Buffer</code>. + * The returned Scala <code>Buffer</code> is backed by the provided Java + * <code>List</code> and any side-effects of using it via the Scala interface will + * be visible via the Java interface and vice versa. + * <p> + * If the Java <code>List</code> was previously obtained from an implicit or + * explicit call of <code>asList(scala.collection.mutable.Buffer)</code> then the original + * Scala <code>Buffer</code> will be returned. + * + * @param l The <code>List</code> to be converted. + * @return A Scala mutable <code>Buffer</code> view of the argument. + */ + implicit def asBuffer[A](l : ju.List[A]) = l match { + case MutableBufferWrapper(wrapped) => wrapped + case _ =>new JListWrapper(l) + } + + /** + * Implicitly converts a Java <code>Set</code> to a Scala mutable <code>Set</code>. + * The returned Scala <code>Set</code> is backed by the provided Java + * <code>Set</code> and any side-effects of using it via the Scala interface will + * be visible via the Java interface and vice versa. + * <p> + * If the Java <code>Set</code> was previously obtained from an implicit or + * explicit call of <code>asSet(scala.collection.mutable.Set)</code> then the original + * Scala <code>Set</code> will be returned. + * + * @param s The <code>Set</code> to be converted. + * @return A Scala mutable <code>Set</code> view of the argument. + */ + implicit def asSet[A](s : ju.Set[A]) = s match { + case MutableSetWrapper(wrapped) => wrapped + case _ =>new JSetWrapper(s) + } + + /** + * Implicitly converts a Java <code>Map</code> to a Scala mutable <code>Map</code>. + * The returned Scala <code>Map</code> is backed by the provided Java + * <code>Map</code> and any side-effects of using it via the Scala interface will + * be visible via the Java interface and vice versa. + * <p> + * If the Java <code>Map</code> was previously obtained from an implicit or + * explicit call of <code>asMap(scala.collection.mutable.Map)</code> then the original + * Scala <code>Map</code> will be returned. + * + * @param m The <code>Map</code> to be converted. + * @return A Scala mutable <code>Map</code> view of the argument. + */ + implicit def asMap[A, B](m : ju.Map[A, B]) = m match { + case MutableMapWrapper(wrapped) => wrapped + case _ =>new JMapWrapper(m) + } + + // Private implementations ... + + case class IteratorWrapper[A](underlying : Iterator[A]) extends ju.Iterator[A] with ju.Enumeration[A] { + def hasNext = underlying.hasNext + def next = underlying.next + def hasMoreElements = underlying.hasNext + def nextElement = underlying.next + def remove = throw new UnsupportedOperationException + } + + case class JIteratorWrapper[A](underlying : ju.Iterator[A]) extends Iterator[A] { + def hasNext = underlying.hasNext + def next = underlying.next + } + + case class JEnumerationWrapper[A](underlying : ju.Enumeration[A]) extends Iterator[A] { + def hasNext = underlying.hasMoreElements + def next = underlying.nextElement + } + + case class IterableWrapper[A](underlying : Iterable[A]) extends ju.AbstractCollection[A] { + def iterator = underlying.elements + def size = underlying.size + override def isEmpty = underlying.isEmpty + } + + case class JIterableWrapper[A](underlying : jl.Iterable[A]) extends Iterable[A] { + def elements = underlying.iterator + def newBuilder[B] = new mutable.ArrayBuffer[B] + } + + case class JCollectionWrapper[A](underlying : ju.Collection[A]) extends Iterable[A] { + def elements = underlying.iterator + override def size = underlying.size + override def isEmpty = underlying.isEmpty + def newBuilder[B] = new mutable.ArrayBuffer[B] + } + + case class MutableBufferWrapper[A](underlying : mutable.Buffer[A]) extends ju.AbstractList[A] { + def size = underlying.length + def get(i : Int) = underlying(i) + override def set(i : Int, elem: A) = { val p = underlying(i) ; underlying(i) = elem ; p } + override def add(elem : A) = { underlying.append(elem) ; true } + override def remove(i : Int) = underlying.remove(i) + } + + case class JListWrapper[A](val underlying : ju.List[A]) extends mutable.Buffer[A] { + def length = underlying.size + override def isEmpty = underlying.isEmpty + override def elements : Iterator[A] = underlying.iterator + def apply(i : Int) = underlying.get(i) + def update(i : Int, elem : A) = underlying.set(i, elem) + def +:(elem : A) = { underlying.subList(0, 0).add(elem) ; this } + def +=(elem : A) = underlying.add(elem) + def insertAll(i : Int, elems : Traversible[A]) = { val ins = underlying.subList(0, i) ; elems.foreach(ins.add(_)) } + def remove(i : Int) = underlying.remove(i) + def clear = underlying.clear + def result = this + } + + case class MutableSetWrapper[A](underlying : mutable.Set[A])(m : Manifest[A]) extends ju.AbstractSet[A] { + self => + def size = underlying.size + override def add(elem: A) = { val sz = underlying.size ; underlying += elem ; sz < underlying.size } + override def remove(elem : AnyRef) = { + m.erasure.isInstance(elem) && { + val sz = underlying.size + underlying -= elem.asInstanceOf[A] + sz > underlying.size + } + } + def iterator = new ju.Iterator[A] { + val ui = underlying.elements + var prev : Option[A] = None + + def hasNext = ui.hasNext + def next = { val e = ui.next ; prev = Some(e) ; e } + def remove = prev match { + case Some(e) => self.remove(e.asInstanceOf[AnyRef]) ; prev = None + case _ => throw new IllegalStateException("next must be called at least once before remove") + } + } + } + + case class JSetWrapper[A](underlying : ju.Set[A]) extends mutable.Set[A] with generic.SetTemplate[A, JSetWrapper[A]] { + override def size = underlying.size + + def elements = underlying.iterator + + def contains(elem: A): Boolean = underlying.contains(elem) + + def +=(elem: A) { underlying.add(elem) } + + def -=(elem: A) { underlying.remove(elem) } + + override def clear = underlying.clear + + override def empty = JSetWrapper(new ju.HashSet[A]) + } + + case class MutableMapWrapper[A, B](underlying : mutable.Map[A, B])(m : Manifest[A]) extends ju.AbstractMap[A, B] { + self => + override def size = underlying.size + + override def put(k : A, v : B) = underlying.put(k, v) match { + case Some(v1) => v1 + case None => null.asInstanceOf[B] + } + + override def remove(k : AnyRef) = { + if (!m.erasure.isInstance(k)) + null.asInstanceOf[B] + else { + val k1 = k.asInstanceOf[A] + underlying.get(k1) match { + case Some(v) => underlying -= k1 ; v + case None => null.asInstanceOf[B] + } + } + } + + override def entrySet : ju.Set[ju.Map.Entry[A, B]] = new ju.AbstractSet[ju.Map.Entry[A, B]] { + def size = self.size + + def iterator = new ju.Iterator[ju.Map.Entry[A, B]] { + val ui = underlying.elements + var prev : Option[A] = None + + def hasNext = ui.hasNext + + def next = { + val (k, v) = ui.next + prev = Some(k) + new ju.Map.Entry[A, B] { + def getKey = k + def getValue = v + def setValue(v1 : B) = self.put(k, v1) + override def equals(other : Any) = other match { + case e : ju.Map.Entry[_, _] => k == e.getKey && v == e.getValue + case _ => false + } + } + } + + def remove = prev match { + case Some(k) => val v = self.remove(k.asInstanceOf[AnyRef]) ; prev = None ; v + case _ => throw new IllegalStateException("next must be called at least once before remove") + } + } + } + } + + case class JMapWrapper[A, B](underlying : ju.Map[A, B]) extends mutable.Map[A, B] with generic.MutableMapTemplate[A, B, JMapWrapper[A, B]] { + override def size = underlying.size + + def get(k : A) = { + val v = underlying.get(k) + if (v != null) + Some(v) + else if(underlying.containsKey(k)) + Some(null.asInstanceOf[B]) + else + None + } + + def update(k : A, v : B) { underlying.put(k, v) } + + def -=(k : A) = { underlying.remove(k) ; this } + + def elements = new Iterator[(A, B)] { + val ui = underlying.entrySet.iterator + def hasNext = ui.hasNext + def next = { val e = ui.next ; (e.getKey, e.getValue) } + } + + override def clear = underlying.clear + + override def empty = JMapWrapper(new ju.HashMap[A, B]) + } +} diff --git a/src/library/scala/collection/LinearSequence.scala b/src/library/scala/collection/LinearSequence.scala new file mode 100755 index 0000000000..fc8d5e9a07 --- /dev/null +++ b/src/library/scala/collection/LinearSequence.scala @@ -0,0 +1,38 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ + + +package scala.collection + +import mutable.ListBuffer +// import immutable.{List, Nil, ::} +import generic._ +import util.control.Breaks._ + +/** Class <code>Linear[A]</code> represents linear sequences of elements. + * For such sequences `isEmpty`, `head` and `tail` are guaranteed to be + * efficient constant time (or near so) operations. + * It does not add any methods to Sequence but overrides several + * methods with optimized implementations. + * + * @author Martin Odersky + * @author Matthias Zenger + * @version 1.0, 16/07/2003 + */ +trait LinearSequence[+A] extends Sequence[A] with LinearSequenceTemplate[A, LinearSequence[A]] { + override protected[this] def newBuilder = LinearSequence.newBuilder + override def traversibleBuilder[B]: Builder[B, LinearSequence[B], Any] = LinearSequence.newBuilder[B] +} + +object LinearSequence extends SequenceFactory[LinearSequence] { + type Coll = LinearSequence[_] + implicit def builderFactory[A]: BuilderFactory[A, LinearSequence[A], Coll] = new BuilderFactory[A, LinearSequence[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, LinearSequence[A], Any] = immutable.LinearSequence.newBuilder[A] +} diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala index ba465efa8b..66c8a78666 100644 --- a/src/library/scala/collection/Map.scala +++ b/src/library/scala/collection/Map.scala @@ -11,188 +11,42 @@ package scala.collection -import Predef._ +import generic._ -object Map { - trait Projection[A, +B] extends Iterable.Projection[(A, B)] with Map[A, B] -} - - -/** <p> -* A map is a collection that maps each key to one or zero values. - * </p> - * <p> - * This trait provides a limited interface, only allowing reading of elements. - * There are two extensions of this trait, in packages - * <code><a href="mutable$content.html" target="contentFrame"> - * scala.collection.mutable</a></code> - * and <code><a href="immutable$content.html" target="contentFrame"> - * scala.collection.immutable</a></code>, which provide functionality for - * adding new key/value mappings to a map. The trait in the first package is - * for maps that are modified destructively, whereas the trait in - * the second package is for immutable maps which create a new map - * when something is added or removed from them. - * </p> +/** A map 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 elements: Iterator[(A, B)] + * def add[B1 >: B](key: A, value: 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 * - * @author Matthias Zenger - * @author Martin Odersky - * @version 1.2, 31/12/2006 + * It might also be a good idea to override methods foreach and size for efficiency. + * + * @note If you do not have speicifc implementations for `add` and `-` in mind, you + * might consider inheriting from `DefaultMap` instead. + * + * @note Of you additions and mutations return the same kind of map as the map you are defining, + * you should inherit from `MapTemplate` as well. */ -trait Map[A, +B] extends PartialFunction[A, B] with Collection[(A, B)] { - - /** Compute the number of key-to-value mappings. - * - * @return the number of mappings - */ - def size: Int - - /** Check if this map maps <code>key</code> to a value and return the - * value if it exists. - * - * @param key the key of the mapping of interest - * @return the value of the mapping, if it exists - */ - def get(key: A): Option[B] - - /** Check if this map maps <code>key</code> to a value. - * Return that value if it exists, otherwise return <code>default</code>. - */ - def getOrElse[B2 >: B](key: A, default: => B2): B2 = - get(key) match { - case Some(v) => v - case None => default - } - - /** Is this an empty map? - * - * @return <code>true</code> iff the map is empty. - */ - override def isEmpty: Boolean = size == 0 +trait Map[A, +B] extends Iterable[(A, B)] with MapTemplate[A, B, Map[A, B]] { + def empty: Map[A, B] = Map.empty - /** Retrieve the value which is associated with the given key. This - * method throws an exception if there is no mapping from the given - * key to a value. - * - * @param key the key - * @return the value associated with the given key. - */ - def apply(key: A): B = get(key) match { - case None => default(key) - case Some(value) => value - } + override protected[this] def newBuilder : Builder[(A, B), Map[A, B], Any] = + throw new UnsupportedOperationException("Map.newBuilder") - /** Is the given key mapped to a value by this map? - * - * @param key the key - * @return <code>true</code> iff there is a mapping for key in this map - */ - def contains(key: A): Boolean = get(key) match { - case None => false - case Some(_) => true - } - - /** Does this map contain a mapping from the given key to a value? - * - * @param key the key - * @return <code>true</code> iff there is a mapping for key in this map - */ - def isDefinedAt(key: A) = contains(key) - - /** Creates an iterator for all keys. - * - * @return an iterator over all keys. - */ - def keys: Iterator[A] = new Iterator[A] { - val iter = Map.this.elements - def hasNext = iter.hasNext - def next = iter.next._1 - } - - /** @return the keys of this map as a set. - */ - def keySet: Set[A] = new Set[A] { - def size = Map.this.size - def contains(key : A) = Map.this.contains(key) - def elements = Map.this.elements.map(_._1) - } - - /** Creates an iterator for a contained values. - * - * @return an iterator over all values. - */ - def values: Iterator[B] = new Iterator[B] { - val iter = Map.this.elements - def hasNext = iter.hasNext - def next = iter.next._2 - } - - /** Compares two maps structurally; i.e. checks if all mappings - * contained in this map are also contained in the other map, - * and vice versa. - * - * @param that the other map - * @return <code>true</code> iff both maps contain exactly the - * same mappings. - */ - override def equals(that: Any): Boolean = that match { - case other: Map[a, b] => - this.size == other.size && this.elements.forall { - case (key, value) => other.get(key.asInstanceOf[a]) match { - case None => false - case Some(otherval) => value == otherval - } - } - case _ => false - } - - /** A hash method compatible with <code>equals</code> - */ - override def hashCode() = - (0 /: elements) ((hash, kv) => hash + kv.hashCode) - - - /** Creates a string representation for this map. - * - * @return a string showing all mappings - */ - override def toString() = - elements.toList.map(kv => kv._1 + " -> " + kv._2).mkString(stringPrefix + "(", ", ", ")") - - /** The default value for the map, returned when a key is not found - * The method implemented here yields an error, - * but it might be overridden in subclasses. - * - * @param key the given key value - * @throws Predef.NoSuchElementException - */ - def default(key: A): B = - throw new NoSuchElementException("key not found: " + key) - - override def projection: Map.Projection[A,B] = new Map.Projection[A, B] { - override def elements = Map.this.elements - override def size = Map.this.size - override def get(key: A): Option[B] = Map.this.get(key) - } - /** non-strict filter based on keys only */ - def filterKeys(p: A => Boolean): Map.Projection[A, B] = new Map.Projection[A, B] { - def elements = Map.this.elements.filter(x => p(x._1)) - def size = { - var sz = 0 - Map.this.foreach(x => if (p(x._1)) sz = sz + 1) - sz - } - override def contains(key: A) = Map.this.contains(key) && p(key) - override def get(key: A) = if (!p(key)) None else Map.this.get(key) - } - /** non-strict map elements using existing key set */ - def mapElements[C](f: B => C) : Map.Projection[A,C] = new Map.Projection[A,C] { - def elements = Map.this.elements.map(e => (e._1, f(e._2))) - def size = Map.this.size - override def contains(key: A) = Map.this.contains(key) - override def get(key: A) = Map.this.get(key).map(f) - } + def mapBuilder[A, B]: Builder[(A, B), Map[A, B], Any] = Map.newBuilder[A, B] +} - /** Defines the prefix of this object's <code>toString</code> representation. - */ - override protected def stringPrefix: String = "Map" +/* Factory object for `Map` class */ +object Map extends ImmutableMapFactory[immutable.Map] { + type Coll = Map[_, _] + def empty[A, B]: immutable.Map[A, B] = immutable.Map.empty + implicit def builderFactory[A, B]: BuilderFactory[(A, B), Map[A, B], Coll] = new BuilderFactory[(A, B), Map[A, B], Coll] { def apply(from: Coll) = from.mapBuilder[A, B] } } diff --git a/src/library/scala/collection/MapProxy.scala b/src/library/scala/collection/MapProxy.scala index 5084989bbd..1c3dd14e36 100644 --- a/src/library/scala/collection/MapProxy.scala +++ b/src/library/scala/collection/MapProxy.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -43,3 +44,4 @@ trait MapProxy[A, +B] extends Map[A, B] with CollectionProxy[(A, B)] { override def filterKeys(p: A => Boolean) = self filterKeys p override def mapElements[C](f: B => C) = self mapElements f } +*/ diff --git a/src/library/scala/collection/RollbackIterator.scala b/src/library/scala/collection/RollbackIterator.scala.disabled index fb994dd168..09ef4b6c3e 100644 --- a/src/library/scala/collection/RollbackIterator.scala +++ b/src/library/scala/collection/RollbackIterator.scala.disabled @@ -34,8 +34,8 @@ class RollbackIterator[+A](underlying: Iterator[A]) extends BufferedIterator.Def } else Some(rollback.length) - /** will rollback all elements iterated during - * <code>f</code>'s execution if <code>f</code> return false + /** will rollback all elements iterated during + * <code>f</code>'s execution if <code>f</code> return false */ def tryRead[T](f: => Option[T]): Option[T] = { val oldLength = initRollback @@ -48,11 +48,11 @@ class RollbackIterator[+A](underlying: Iterator[A]) extends BufferedIterator.Def val sz = oldLength.getOrElse(0) val i = rollback.drop(sz).reverse.elements while (i.hasNext) putBack(i.next) - if (oldLength.isEmpty) rollback = null + if (oldLength.isEmpty) rollback = null else rollback.reduceToSize(sz) } } - if (!g.isEmpty && oldLength.isEmpty) + if (!g.isEmpty && oldLength.isEmpty) rollback = null g @@ -72,7 +72,7 @@ class RollbackIterator[+A](underlying: Iterator[A]) extends BufferedIterator.Def f(in) } - /** returns true if any elements are iterated over during <code>f</code>'s execution + /** returns true if any elements are iterated over during <code>f</code>'s execution */ def read(f: => Unit): Boolean = remember[Boolean] { f; seq => !seq.isEmpty @@ -81,7 +81,7 @@ class RollbackIterator[+A](underlying: Iterator[A]) extends BufferedIterator.Def /** if elements of <code>seq</code> will be iterated over next in this iterator, * returns true and iterates over these elements */ - override def readIfStartsWith(seq : Seq[Any]) : Boolean = + override def readIfStartsWith(seq : Seq[Any]) : Boolean = !tryRead{if (seq.forall(a => hasNext && next == a)) Some(()) else None}.isEmpty } diff --git a/src/library/scala/collection/Sequence.scala b/src/library/scala/collection/Sequence.scala new file mode 100755 index 0000000000..18f17d0513 --- /dev/null +++ b/src/library/scala/collection/Sequence.scala @@ -0,0 +1,55 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ + + +package scala.collection + +import mutable.ListBuffer +// import immutable.{List, Nil, ::} +import generic._ +import util.control.Breaks._ + +/** Class <code>Sequence[A]</code> represents sequences of elements + * of type <code>A</code>. + * It adds the following methods to class Iterable: + * `length`, `lengthCompare`, `apply`, `isDefinedAt`, `segmentLength`, `prefixLengh`, + * `indexWhere`, `indexOf`, `lastIndexWhere`, `lastIndexOf`, `reverse`, `reversedElements`, + * `startsWith`, `endsWith`, `indexOfSeq`. + * + * + * @author Martin Odersky + * @author Matthias Zenger + * @version 1.0, 16/07/2003 + */ +trait Sequence[+A] extends PartialFunction[Int, A] with Iterable[A] with SequenceTemplate[A, Sequence[A]] { + override protected[this] def newBuilder = Sequence.newBuilder + override def traversibleBuilder[B]: Builder[B, Sequence[B], Any] = Sequence.newBuilder[B] +} + +object Sequence extends SequenceFactory[Sequence] { + + type Coll = Sequence[_] + implicit def builderFactory[A]: BuilderFactory[A, Sequence[A], Coll] = new BuilderFactory[A, Sequence[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Sequence[A], Any] = immutable.Sequence.newBuilder[A] + + /** @deprecated use View instead + */ + @deprecated type Projection[A] = SequenceView[A, Coll] + + /** @deprecated use Sequence(value) instead */ + @deprecated def singleton[A](value: A) = Sequence(value) + + /** Builds a singleton sequence. + * + * @deprecated use <code>Sequence(x)</code> instead. + */ + @deprecated def single[A](x: A) = singleton(x) +} + diff --git a/src/library/scala/collection/SequenceProxy.scala b/src/library/scala/collection/SequenceProxy.scala new file mode 100644 index 0000000000..40ad16f312 --- /dev/null +++ b/src/library/scala/collection/SequenceProxy.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ + + +package scala.collection + +import generic._ + +// Methods could be printed by cat Traversibe.scala | egrep '^ (override )?def' + + +/** This trait implements a proxy for iterable objects. It forwards + * all calls to a different iterable object + * + * @author Martin Odersky + * @version 2.8 + */ +trait SequenceProxy[+A] extends Sequence[A] with SequenceProxyTemplate[A, Sequence[A]] diff --git a/src/library/scala/collection/Set.scala b/src/library/scala/collection/Set.scala index 47cf7871e0..691953bdf1 100644 --- a/src/library/scala/collection/Set.scala +++ b/src/library/scala/collection/Set.scala @@ -8,115 +8,33 @@ // $Id$ - package scala.collection +import generic._ /** <p> * A set is a collection that includes at most one of any object. * </p> * <p> - * This trait provides a limited interface, only allowing reading of elements. - * There are two extensions of this trait, in packages - * <code><a href="mutable$content.html" target="contentFrame"> - * scala.collection.mutable</a></code> - * and <code><a href="immutable$content.html" target="contentFrame"> - * scala.collection.immutable</a></code>, which provide functionality for - * adding and removing objects from the set. The trait in the first package is - * for sets that are modified destructively, whereas the trait in - * the second package is for immutable sets which create a new set - * when something is added or removed to them. * * @author Matthias Zenger * @author Martin Odersky - * @version 2.0, 01/01/2007 + * @version 2.8 */ -trait Set[A] extends (A => Boolean) with Collection[A] { - - /** Returns the number of elements in this set. - * - * @return number of set elements. - */ - def size: Int - - /** Checks if this set contains element <code>elem</code>. - * - * @param elem the element to check for membership. - * @return <code>true</code> iff <code>elem</code> is contained in - * this set. - */ - def contains(elem: A): Boolean - - /** This method allows sets to be interpreted as predicates. - * It returns <code>true</code>, iff this set contains element - * <code>elem</code>. - * - * @param elem the element to check for membership. - * @return <code>true</code> iff <code>elem</code> is contained in - * this set. - */ - def apply(elem: A): Boolean = contains(elem) - - /** Checks if this set is empty. - * - * @return <code>true</code> iff there is no element in the set. - */ - override def isEmpty: Boolean = size == 0 - - /** Checks if this set is a subset of set <code>that</code>. - * - * @param that another set. - * @return <code>true</code> iff the other set is a superset of - * this set. - * todo: rename to isSubsetOf - */ - def subsetOf(that: Set[A]): Boolean = forall(that.contains) - - @deprecated def *(that : Set[A]) : Set[A] = this ** that +trait Set[A] extends (A => Boolean) with Iterable[A] with SetTemplate[A, Set[A]] { + def empty = Set.empty + override def traversibleBuilder[B]: Builder[B, Set[B], Any] = Set.newBuilder[B] +} - /** Intersect. It computes an intersection with set <code>that</code>. - * It removes all the elements that are not present in <code>that</code>. - * - * @param that the set to intersect with - */ - def **(that : Set[A]) : Set[A] = { - val min = Math.min(size, that.size) - val buf = new Array[A](min) - var count = 0 - val i = elements - while (i.hasNext) { - val a = i.next - if (that.contains(a)) { - buf(count) = a - count += 1 - } - } - if (count == size) this - else if (count == that.size) that - else { - import scala.collection.mutable.HashSet - val ret = new HashSet[A] - ret ++= buf.projection.take(count) - ret - } - } - /** Compares this set with another object and returns true, iff the - * other object is also a set which contains the same elements as - * this set. - * - * @param that the other object - * @note not necessarily run-time type safe. - * @return <code>true</code> iff this set and the other set - * contain the same elements. - */ - override def equals(that: Any): Boolean = that match { - case other: Set[_] => - this.size == other.size && subsetOf(other.asInstanceOf[Set[A]]) - case _ => - false - } +/* Factory object for `Set` class */ +object Set extends SetFactory[Set] { + def empty[A]: Set[A] = immutable.Set.empty[A] + type Coll = Set[_] + implicit def builderFactory[A]: BuilderFactory[A, Set[A], Coll] = new BuilderFactory[A, Set[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } +} - override def hashCode() = +/* !!! what to do about this? +override def hashCode() = (0 /: this)((hash, e) => hash + e.hashCode()) override def toArray[B >: A]: Array[B] = { @@ -128,4 +46,4 @@ trait Set[A] extends (A => Boolean) with Collection[A] { /** Defines the prefix of this object's <code>toString</code> representation. */ override protected def stringPrefix : String = "Set" -} +*/ diff --git a/src/library/scala/collection/SetProxy.scala b/src/library/scala/collection/SetProxy.scala index e80c28a8d5..7ed2d7f957 100644 --- a/src/library/scala/collection/SetProxy.scala +++ b/src/library/scala/collection/SetProxy.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -28,3 +29,4 @@ trait SetProxy[A] extends Set[A] with IterableProxy[A] { def contains(elem: A): Boolean = self.contains(elem) override def subsetOf(that: Set[A]): Boolean = self.subsetOf(that) } +*/ diff --git a/src/library/scala/collection/SortedMap.scala b/src/library/scala/collection/SortedMap.scala index e2bbdeab8f..55eab25648 100644 --- a/src/library/scala/collection/SortedMap.scala +++ b/src/library/scala/collection/SortedMap.scala @@ -7,38 +7,20 @@ \* */ // $Id$ +package scala.collection -package scala.collection; +import generic._ /** A map whose keys are sorted. * * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 */ -trait SortedMap[K,+E] extends Map[K,E] with Sorted[K,Tuple2[K,E]] { - override def firstKey : K = elements.next._1; - override def lastKey : K = { - val i = elements; - var last : K = i.next._1; - while (i.hasNext) last = i.next._1; - last; - } +trait SortedMap[A, +B] extends Map[A, B] with SortedMapTemplate[A, B, SortedMap[A, B]] { + /** Needs to be overridden in subclasses. */ + override def empty: SortedMap[A, B] = throw new UnsupportedOperationException("SortedMap.empty") + override protected[this] def newBuilder : Builder[(A, B), SortedMap[A, B], Any] = + throw new UnsupportedOperationException("SortedMap.newBuilder") - // XXX: implement default version - override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E]; - override def from(from: K) = rangeImpl(Some(from), None); - override def until(until: K) = rangeImpl(None, Some(until)); - override def range(from: K, until: K) = rangeImpl(Some(from),Some(until)); - - protected class DefaultKeySet extends SortedSet[K] { - def size = SortedMap.this.size - def contains(key : K) = SortedMap.this.contains(key) - def elements = SortedMap.this.elements.map(_._1) - def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0, k1); - override def rangeImpl(from : Option[K], until : Option[K]) : SortedSet[K] = { - val map = SortedMap.this.rangeImpl(from,until); - new map.DefaultKeySet; - } - } - // XXX: implement default version - override def keySet : SortedSet[K] = new DefaultKeySet; } diff --git a/src/library/scala/collection/SortedSet.scala b/src/library/scala/collection/SortedSet.scala index 8046a8b002..635e1f9026 100644 --- a/src/library/scala/collection/SortedSet.scala +++ b/src/library/scala/collection/SortedSet.scala @@ -7,42 +7,19 @@ \* */ // $Id$ +// !!! todo: integrate in new collections library package scala.collection -/** Analogous to a Java sorted set. +import generic._ + +/** A sorted set. * * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 */ -trait SortedSet[A] extends Set[A] with Sorted[A, A] { - - override def keySet = this - - override def firstKey: A = { - val i = elements - if (i.hasNext) i.next - else throw new NoSuchElementException - } - - override def lastKey: A = { - var last: A = null.asInstanceOf[A] - val i = elements - while (i.hasNext) last = i.next; - if (last == null) throw new NoSuchElementException - else last - } - - override def rangeImpl(from: Option[A], until: Option[A]): SortedSet[A] - - override def from(from: A) = rangeImpl(Some(from), None) - - override def until(until: A) = rangeImpl(None, Some(until)) - - override def range(from: A, until: A) = rangeImpl(Some(from),Some(until)) - - override def subsetOf(that: Set[A]): Boolean = that match { - case that: SortedSet[_] => that.hasAll(elements) - case that => super.subsetOf(that) - } - +trait SortedSet[A] extends Set[A] with SortedSetTemplate[A, SortedSet[A]] { + /** Needs to be overridden in subclasses. */ + override def empty: SortedSet[A] = throw new UnsupportedOperationException("SortedMap.empty") } diff --git a/src/library/scala/collection/Traversible.scala b/src/library/scala/collection/Traversible.scala new file mode 100755 index 0000000000..886fd1c767 --- /dev/null +++ b/src/library/scala/collection/Traversible.scala @@ -0,0 +1,213 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Traversible.scala 15188 2008-05-24 15:01:02Z stepancheg $ +package scala.collection + +// import immutable.{List, Stream, Nil} +import mutable.{Buffer, ArrayBuffer, ListBuffer} +import util.control.Breaks._ +import generic._ + +/** A template trait for traversible collections. + * + * Collection classes mixing in this trait provide a method + * <code>foreach</code> which traverses all the + * elements contained in the collection, applying a given procedure to each. + * They also provide a method `newBuilder` + * which creates a builder for collections of the same kind. + * + * @author Martin Odersky + * @version 2.8 + */ +trait Traversible[+A] extends TraversibleTemplate[A, Traversible[A]] { + protected[this] def newBuilder = Traversible.newBuilder + def traversibleBuilder[B]: Builder[B, Traversible[B], Any] = Traversible.newBuilder[B] + + /* The following methods are inherited from TraversibleTemplate + * + override def isEmpty: Boolean + override def size: Int + override def hasDefiniteSize + override def ++[B >: A, That](that: Traversible[B])(implicit bf: BuilderFactory[B, That, Traversible[A]]): That + override def ++[B >: A, That](that: Iterator[B])(implicit bf: BuilderFactory[B, That, Traversible[A]]): That + override def map[B, That](f: A => B)(implicit bf: BuilderFactory[B, That, Traversible[A]]): That + override def flatMap[B, That](f: A => Traversible[B])(implicit bf: BuilderFactory[B, That, Traversible[A]]): That + override def filter(p: A => Boolean): Traversible[A] + override def remove(p: A => Boolean): Traversible[A] + override def partition(p: A => Boolean): (Traversible[A], Traversible[A]) + override def groupBy[K](f: A => K): Map[K, Traversible[A]] + override def foreach(f: A => Unit): Unit + override def forall(p: A => Boolean): Boolean + override def exists(p: A => Boolean): Boolean + override def count(p: A => Boolean): Int + override def find(p: A => Boolean): Option[A] + override def foldLeft[B](z: B)(op: (B, A) => B): B + override def /: [B](z: B)(op: (B, A) => B): B + override def foldRight[B](z: B)(op: (A, B) => B): B + override def :\ [B](z: B)(op: (A, B) => B): B + override def reduceLeft[B >: A](op: (B, A) => B): B + override def reduceLeftOpt[B >: A](op: (B, A) => B): Option[B] + override def reduceRight[B >: A](op: (A, B) => B): B + override def reduceRightOpt[B >: A](op: (A, B) => B): Option[B] + override def head: A + override def headOption: Option[A] + override def tail: Traversible[A] + override def last: A + override def lastOption: Option[A] + override def init: Traversible[A] + override def take(n: Int): Traversible[A] + override def drop(n: Int): Traversible[A] + override def slice(from: Int, until: Int): Traversible[A] + override def takeWhile(p: A => Boolean): Traversible[A] + override def dropWhile(p: A => Boolean): Traversible[A] + override def span(p: A => Boolean): (Traversible[A], Traversible[A]) + override def splitAt(n: Int): (Traversible[A], Traversible[A]) + override def copyToBuffer[B >: A](dest: Buffer[B]) + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) + override def copyToArray[B >: A](xs: Array[B], start: Int) + override def toArray[B >: A]: Array[B] + override def toList: List[A] + override def toIterable: Iterable[A] + override def toSequence: Sequence[A] + override def toStream: Stream[A] +// override def sortWith(lt : (A,A) => Boolean): Traversible[A] + override def mkString(start: String, sep: String, end: String): String + override def mkString(sep: String): String + override def mkString: String + override def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder + override def addString(b: StringBuilder, sep: String): StringBuilder + override def addString(b: StringBuilder): StringBuilder + override def toString + override def stringPrefix : String + override def view + override def view(from: Int, until: Int): TraversibleView[A, Traversible[A]] + */ +} + +/** Factory methods and utilities for instances of type Traversible */ +object Traversible extends TraversibleFactory[Traversible] { self => + + type Coll = Traversible[_] + implicit def builderFactory[A]: BuilderFactory[A, Traversible[A], Coll] = new BuilderFactory[A, Traversible[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Traversible[A], Any] = immutable.Traversible.newBuilder[A] + + /** A wrapper class which adds `min` and `max` methods to iterables of an element type that has an Ordering. + */ + class ComparableTraversibleOps[A](self: Traversible[A], cmp: Ordering[A]) { + + /** Returns the minimal element of the wrapped iterable `self` with respect to the given ordering `cmp` */ + def min: A = { + require(!self.isEmpty, "min(<empty>)") + var acc = self.head + for (x <- self) + if (cmp.lt(x, acc)) acc = x + acc + } + + /** Returns the maximal element of the wrapped iterable `self` with respect to the given ordering `cmp` */ + def max: A = { + require(!self.isEmpty, "max(<empty>)") + var acc = self.head + for (x <- self) + if (cmp.gt(x, acc)) acc = x + acc + } + } + + /** A wrapper class which adds `sum` and `product` methods to iterables of an element type that is `Numeric`. + */ + class NumericTraversibleOps[A](self: Traversible[A], num: Numeric[A]) { + + /** Returns the sum of all elements of the wrapped iterable `self` with respect to the numeric operations in `num` */ + def sum: A = { + var acc = num.zero + for (x <- self) acc = num.plus(acc, x) + acc + } + + /** Returns the product of all elements of the wrapped iterable `self` with respect to the numeric operations in `num` */ + def product: A = { + var acc = num.one + for (x <- self) acc = num.times(acc, x) + acc + } + } + + /** A wrapper class which adds `flatten` and `transpose` methods to iterables or iterable element type`. + */ + class TraversibleTraversibleOps[This <: Traversible[Traversible[A]], A](self: This) { + + /** Returns the concatenation of all elements of the wrapped iterable `self` */ + def flatten[That](implicit bf: BuilderFactory[A, That, This]): That = { + val b = bf(self) + for (xs <- self) + b ++= xs + b.result + } + + /** Returns the transposition of the wrapped iterable `self`: rows become columns and columns become rows. + */ + def transpose[Row, That](implicit bf: BuilderFactory[A, Row, This], bbf: BuilderFactory[Row, That, This]): That = { + val bs: Array[Builder[A, Row, This]] = self.head.map(_ => bf(self))(Traversible.builderFactory[Builder[A, Row, This]]).toArray + for (xs <- self) { + var i = 0 + for (x <- xs) { + bs(i) += x + i += 1 + } + } + val bb = bbf(self) + for (b <- bs) bb += b.result + bb.result + } + } + + /** A wrapper class which adds an `unzip` method to iterable whose elements are pairs. + */ + class PairTraversibleOps[This <: Traversible[(A1, A2)], A1, A2](self: This) { + + /** Returns a pair of iterables consisting of the first, respectively second, component of all + * elements in the wrapped iterable `self`. + */ + def unzip[That1, That2](implicit bf1: BuilderFactory[A1, That1, This], bf2: BuilderFactory[A2, That2, This]): (That1, That2) = { + val b1 = bf1(self) + val b2 = bf2(self) + for ((x1, x2) <- self) { + b1 += x1 + b2 += x2 + } + (b1.result, b2.result) + } + } + + /** Implicit wrapper conversion of iterables with elements admitting comparison. + * @see ComparableTraversibleOps + */ + implicit def comparableTraversibleWrapper[A](self: Traversible[A])(implicit cmp: Ordering[A]) = + new ComparableTraversibleOps(self, cmp) + + /** Implicit wrapper conversion of iterables with numeric elements. + * @see NumericTraversibleOps + */ + implicit def numericTraversibleWrapper[A](self: Traversible[A])(implicit num: Numeric[A]) = + new NumericTraversibleOps(self, num) + + /** Implicit wrapper conversion of iterables with iterable elements. + * @see TraversibleTraversibleOps + */ + implicit def traversibleTraversibleWrapper[This <: Traversible[Traversible[A]], A](self: This) = + new TraversibleTraversibleOps[This, A](self) // !!! error if type parameters are omitted + + /** Implicit wrapper conversion of iterables with pairs as elements. + * @see PairTraversibleOps + */ + implicit def pairTraversibleWrapper[This <: Traversible[(A1, A2)], A1, A2](self: This) = + new PairTraversibleOps[This, A1, A2](self) +} + diff --git a/src/library/scala/collection/TraversibleProxy.scala b/src/library/scala/collection/TraversibleProxy.scala new file mode 100644 index 0000000000..edff865af2 --- /dev/null +++ b/src/library/scala/collection/TraversibleProxy.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ + + +package scala.collection + +import generic._ + +// Methods could be printed by cat TraversibeTemplate.scala | egrep '^ (override )?def' + + +/** This trait implements a proxy for traversible objects. It forwards + * all calls to a different traversible object + * + * @author Martin Odersky + * @version 2.8 + */ +trait TraversibleProxy[+A] extends Traversible[A] with TraversibleProxyTemplate[A, Traversible[A]] diff --git a/src/library/scala/collection/Vector.scala b/src/library/scala/collection/Vector.scala new file mode 100755 index 0000000000..fea38a774e --- /dev/null +++ b/src/library/scala/collection/Vector.scala @@ -0,0 +1,33 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $ + +package scala.collection + +import generic._ +import mutable.ArrayBuffer + +/** Sequences that support O(1) element access and O(1) length computation. + * This class does not add any methods to Sequence but overrides several + * methods with optimized implementations. + * + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ +trait Vector[+A] extends Sequence[A] with VectorTemplate[A, Vector[A]] { + override protected[this] def newBuilder = Vector.newBuilder + override def traversibleBuilder[B]: Builder[B, Vector[B], Any] = Vector.newBuilder[B] +} + +object Vector extends SequenceFactory[Vector] { + type Coll = Vector[_] + implicit def builderFactory[A]: BuilderFactory[A, Vector[A], Coll] = new BuilderFactory[A, Vector[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Vector[A], Any] = mutable.Vector.newBuilder[A] +} diff --git a/src/library/scalax/collection/generic/Addable.scala b/src/library/scala/collection/generic/Addable.scala index 40a4f60e6e..ea45be91f3 100755 --- a/src/library/scalax/collection/generic/Addable.scala +++ b/src/library/scala/collection/generic/Addable.scala @@ -8,17 +8,17 @@ // $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ -package scalax.collection.generic +package scala.collection.generic -/** This class represents collections that can be augmented using a += operator. +/** This class represents collections that can be augmented usmutableing a += operator. * * @autor Martin Odersky * @owner Martin Odersky * @version 2.8 */ -trait Addable[+C <: Addable[C, A], A] { +trait Addable[A, +This <: Addable[A, This]] { self => - protected def thisCC: C + protected def thisCollection: This /** Adds a single element to this collection and returns * either the collection itself (if it is mutable), or a new collection @@ -26,7 +26,7 @@ trait Addable[+C <: Addable[C, A], A] { * * @param elem the element to add. */ - def +(elem: A): C + def + (elem: A): This /** Adds two or more elements to this collection and returns * either the collection itself (if it is mutable), or a new collection @@ -36,8 +36,8 @@ trait Addable[+C <: Addable[C, A], A] { * @param elem2 the second element to add. * @param elems the remaining elements to add. */ - def +(elem1: A, elem2: A, elems: A*): C = - thisCC + elem1 + elem2 ++ elems.asInstanceOf[Iterable[A]] // !@! + def + (elem1: A, elem2: A, elems: A*): This = + this + elem1 + elem2 ++ Iterable.fromOld(elems) /** Adds a number of elements provided by an iterable object * via its <code>elements</code> method and returns @@ -46,7 +46,7 @@ trait Addable[+C <: Addable[C, A], A] { * * @param iter the iterable object. */ - def ++(iter: Iterable[A]): C = (thisCC /: iter) (_ + _) + def ++ (iter: Traversible[A]): This = (thisCollection /: iter) (_ + _) /** Adds a number of elements provided by an iterator * via its <code>elements</code> method and returns @@ -55,7 +55,7 @@ trait Addable[+C <: Addable[C, A], A] { * * @param iter the iterator */ - def ++(iter: Iterator[A]): C = (thisCC /: iter) (_ + _) + def ++ (iter: Iterator[A]): This = (thisCollection /: iter) (_ + _) } diff --git a/src/library/scala/collection/generic/AddingBuilder.scala b/src/library/scala/collection/generic/AddingBuilder.scala new file mode 100755 index 0000000000..3b44e70a6a --- /dev/null +++ b/src/library/scala/collection/generic/AddingBuilder.scala @@ -0,0 +1,26 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ + +package scala.collection.generic + +// import collection.immutable.{List, Nil, ::} + +/** The canonical builder for collections that are addable, i.e. that support an efficient + method + * which adds an element to the collection. + * Collections are built from their empty element using this + method. + * @param empty The empty element of the collection. + */ +class AddingBuilder[A, Coll <: Addable[A, Coll] with Iterable[A] with IterableTemplate[A, Coll]](empty: Coll) +extends Builder[A, Coll, Any] { + protected var elems: Coll = empty + def +=(x: A) { elems = elems + x } + def clear() { elems = empty } + def result: Coll = elems +} diff --git a/src/library/scala/collection/generic/BitSetTemplate.scala b/src/library/scala/collection/generic/BitSetTemplate.scala new file mode 100755 index 0000000000..406ba1d431 --- /dev/null +++ b/src/library/scala/collection/generic/BitSetTemplate.scala @@ -0,0 +1,158 @@ +package scala.collection.generic + +import BitSetTemplate._ +import generic._ + +/** common base class for mutable and immutable bit sets + */ +trait BitSetTemplate[+This <: BitSetTemplate[This] with Set[Int]] extends SetTemplate[Int, This] { self => + + /** The number of words (each with 64 bits) making up the set */ + protected def nwords: Int + + /** The words at index `idx', or 0L if outside the range of the set + * @pre idx >= 0 + */ + protected def word(idx: Int): Long + + /** Update word at index `idx`; enlarge set if `idx` outside range of set + */ + protected def updateWord(idx: Int, w: Long): This + + /** Create a new set of this kind from an array of longs + */ + protected def fromArray(elems: Array[Long]): This + + /** Adds element to bitset, reusing set if its mutable. + */ + override def + (elem: Int): This = { + require(elem >= 0) + if (contains(elem)) thisCollection + else { + val idx = elem >> LogWL + updateWord(idx, word(idx) | (1L << elem)) + } + } + + /** Removes element to bitset, reusing set if its mutable. + */ + override def - (elem: Int): This = { + require(elem >= 0) + if (contains(elem)) { + val idx = elem >> LogWL + updateWord(idx, word(idx) & ~(1L << elem)) + } else thisCollection + } + + /** The number of elements in the bitset. + */ + override def size: Int = { + var s = 0 + var i = nwords + while (i > 0) { + i -= 1 + s += popCount(word(i)) + } + s + } + + def elements = new Iterator[Int] { + private var current = 0 + private val end = nwords * WordLength + def hasNext: Boolean = { + while (current < end && !self.contains(current)) current += 1 + current < end + } + def next(): Int = + if (hasNext) { val r = current; current += 1; r } + else Iterator.empty.next + } + + override def foreach(f: Int => Unit) { + for (i <- 0 until nwords) { + val w = word(i) + for (j <- i * WordLength until (i + 1) * WordLength) { + if ((w & (1L << j)) != 0) f(j) + } + } + } + + /** A new bitset which is the logical or of this set and the given argument set. + */ + def | (other: BitSet): This = { + val len = this.nwords max other.nwords + val words = new Array[Long](len) + for (idx <- 0 until len) + words(idx) = this.word(idx) | other.word(idx) + fromArray(words) + } + + /** A new bitset which is the logical and of this set and the given argument set. + */ + def & (other: BitSet): This = { + val len = this.nwords min other.nwords + val words = new Array[Long](len) + for (idx <- 0 until len) + words(idx) = this.word(idx) & other.word(idx) + fromArray(words) + } + + /** A new bitset which is the logical and-not of this set and the given argument set. + */ + def &~ (other: BitSet): This = { + val len = this.nwords + val words = new Array[Long](len) + for (idx <- 0 until len) + words(idx) = this.word(idx) & ~other.word(idx) + fromArray(words) + } + + /** A new bitset which is the logical exclusive or of this set and the given argument set. + */ + def ^ (other: BitSet): This = { + val len = this.nwords max other.nwords + val words = new Array[Long](len) + for (idx <- 0 until len) + words(idx) = this.word(idx) ^ other.word(idx) + fromArray(words) + } + + /** Does the set contain the given element? + */ + def contains(elem: Int): Boolean = + 0 <= elem && (word(elem >> LogWL) & (1L << elem)) != 0 + + /** Is the set a subset of the given bitset + */ + def subSet(other: BitSet): Boolean = + (0 until nwords) forall (idx => (this.word(idx) & ~ other.word(idx)) == 0L) + + /** Add bitset elements as numbers to string buffer + */ + override def addString(sb: StringBuilder, start: String, sep: String, end: String) = { + sb append start + var pre = "" + for (i <- 0 until nwords * WordLength) + if (contains(i)) { + sb append pre append i + pre = sep + } + sb append end + } +} + +object BitSetTemplate { + private val LogWL = 6 + private val WordLength = 64 + + private val pc1: Array[Int] = { + def countBits(x: Int): Int = if (x == 0) 0 else x % 2 + countBits(x >>> 1) + Array.fromFunction(countBits _)(256) + } + + private def popCount(w: Long): Int = { + def pc2(w: Int) = if (w == 0) 0 else pc1(w & 0xff) + pc1(w >>> 8) + def pc4(w: Int) = if (w == 0) 0 else pc2(w & 0xffff) + pc2(w >>> 16) + if (w == 0) 0 else pc4(w.toInt) + pc4((w >>> 32).toInt) + } +} diff --git a/src/library/scalax/collection/mutable/Buffer.scala b/src/library/scala/collection/generic/BufferTemplate.scala index 3d0eaec84e..a946c2bdb3 100644..100755 --- a/src/library/scalax/collection/mutable/Buffer.scala +++ b/src/library/scala/collection/generic/BufferTemplate.scala @@ -9,14 +9,9 @@ // $Id: Buffer.scala 15799 2008-08-15 18:23:54Z odersky $ -package scalax.collection.mutable +package scala.collection.generic -import generic._ - -/* Factory object for `Buffer` trait */ -object Buffer extends SequenceFactory[Buffer] { - def apply[A](args: A*): Buffer[A] = ArrayBuffer.apply(args: _*) -} +import mutable.Buffer /** Buffers are used to create sequences of elements incrementally by * appending, prepending, or inserting new elements. It is also @@ -28,15 +23,17 @@ object Buffer extends SequenceFactory[Buffer] { * @version 2.8 */ @cloneable -trait Buffer[A] extends Sequence[A] - with SequenceTemplate[Buffer, A] - with Addable[Buffer[A], A] - with Subtractable[Buffer[A], A] - with Growable[A] +trait BufferTemplate[A, +This <: BufferTemplate[A, This] with Buffer[A]] + extends Growable[A] with Shrinkable[A] // with Scriptable[Message[(Location, A)]] - with Cloneable[Buffer[A]] -{ + with Addable[A, This] + with Subtractable[A, This] + with Cloneable[This] + with SequenceTemplate[A, This] +{ self => + + import collection.{Iterable, Traversible} // Abstract methods from Vector: @@ -52,25 +49,19 @@ trait Buffer[A] extends Sequence[A] * @param newelem the new element. * @throws IndexOutofBoundsException if the index is not valid */ - def update(n: Int, newelem: A): Unit + def update(n: Int, newelem: A) /** Return number of elements in the buffer */ def length: Int - /** Create a new buffer of the same kind as this one */ - def newBuilder[B]: Builder[Buffer, B] = new ArrayBuffer[B] - - override def newBuilder[B](sizeHint: Int): Builder[Buffer, B] = - new ArrayBuffer[B](sizeHint) - // Abstract methods from Appendable /** Append a single element to this buffer. * * @param elem the element to append. */ - def +=(elem: A): Unit + def +=(elem: A) /** Clears the buffer contents. */ @@ -82,11 +73,11 @@ trait Buffer[A] extends Sequence[A] * the identity of the buffer. * @param elem the element to prepend. */ - def +:(elem: A): this.type + def +:(elem: A): This /** Append a single element to this buffer and return the identity of the buffer */ - def +(elem: A): this.type = { +=(elem); this } + def +(elem: A): This = { +=(elem); thisCollection } /** Inserts new elements at the index <code>n</code>. Opposed to method * <code>update</code>, this method will not replace an element with a @@ -96,26 +87,23 @@ trait Buffer[A] extends Sequence[A] * @param iter the iterable object providing all elements to insert. * @throws IndexOutofBoundsException if the index is not valid */ - def insertAll(n: Int, iter: Iterable[A]): Unit + def insertAll(n: Int, iter: Traversible[A]) - /** Removes a number of elements from a given index position. + + /** Removes the element on a given index position. * * @param n the index which refers to the element to delete. - * @param count the number of elements to delete - * @throws IndexOutofBoundsException if the index is not valid */ - def remove(n: Int, count: Int): Unit - -// Concrete methods + def remove(n: Int): A - /** Removes the element on a given index position. + /** Removes a number of elements from a given index position. * * @param n the index which refers to the element to delete. + * @param count the number of elements to delete + * @throws IndexOutofBoundsException if the index is not valid */ - def remove(n: Int): A = { - val elem = this(n) - remove(n, 1) - elem + def remove(n: Int, count: Int) { + for (i <- 0 until count) remove(n) } /** Removes a single element from this buffer, at its first occurrence. @@ -133,14 +121,14 @@ trait Buffer[A] extends Sequence[A] * * @param x the element to remove. */ - def -(elem: A): this.type = { -=(elem); this } + def - (elem: A): This = { -=(elem); thisCollection } /** Prepend two ore more elements to this buffer and return * the identity of the buffer. * @param elem the element to prepend. */ - def +:(elem1: A, elem2: A, elems: A*): this.type = - elem1 +: elem2 +: (elems.asInstanceOf[Iterable[A]]) ++: this // !@! + def +:(elem1: A, elem2: A, elems: A*): This = + (elem1 +: elem2 +: Iterable.fromOld(elems) ++: thisCollection).asInstanceOf[This] // !!! does not work yet because conrete overrides abstract /** Prepends a number of elements provided by an iterable object * via its <code>elements</code> method. The identity of the @@ -148,7 +136,7 @@ trait Buffer[A] extends Sequence[A] * * @param iter the iterable object. */ - def ++:(iter: Iterable[A]): this.type = { for (x <- iter) x +: this; this } + def ++:(iter: Traversible[A]): This = { for (x <- iter) x +: this; thisCollection } /** Prepends a number of elements provided by an iterator * The identity of the buffer is returned. @@ -156,26 +144,26 @@ trait Buffer[A] extends Sequence[A] * @param iter the iterator * @return the updated buffer. */ - def ++:(iter: Iterator[A]): this.type = { for (x <- iter) x +: this; this } + def ++:(iter: Iterator[A]): This = { for (x <- iter) x +: this; thisCollection } /** Appends a elements to this buffer. * * @param elems the elements to append. */ - def append(elems: A*) { this ++= elems.asInstanceOf[Iterable[A]] } // !@! + def append(elems: A*) { this ++= Iterable.fromOld(elems) } /** Appends a number of elements provided by an iterable object * via its <code>elements</code> method. * * @param iter the iterable object. */ - def appendAll(iter: Iterable[A]) { this ++= iter } + def appendAll(iter: Traversible[A]) { this ++= iter } /** Prepend given elements to this list. * * @param elem the element to prepend. */ - def prepend(elems: A*) { elems.asInstanceOf[Iterable[A]] ++: this } // !@! + def prepend(elems: A*) { Iterable.fromOld(elems) ++: this } /** Prepends a number of elements provided by an iterable object * via its <code>elements</code> method. The identity of the @@ -183,7 +171,7 @@ trait Buffer[A] extends Sequence[A] * * @param iter the iterable object. */ - def prependAll(iter: Iterable[A]) { iter ++: this } + def prependAll(iter: Traversible[A]) { iter ++: this } /** Prepends a number of elements provided by an iterable object * via its <code>elements</code> method. The identity of the @@ -200,7 +188,7 @@ trait Buffer[A] extends Sequence[A] * @param n the index where a new element will be inserted. * @param elems the new elements to insert. */ - def insert(n: Int, elems: A*) { insertAll(n, elems.asInstanceOf[Iterable[A]]) } // !@! + def insert(n: Int, elems: A*) { insertAll(n, Iterable.fromOld(elems)) } /** Removes the first <code>n</code> elements. * @@ -266,9 +254,7 @@ trait Buffer[A] extends Sequence[A] i += 1 } } - } - diff --git a/src/library/scala/collection/generic/Builder.scala b/src/library/scala/collection/generic/Builder.scala new file mode 100755 index 0000000000..675596da2b --- /dev/null +++ b/src/library/scala/collection/generic/Builder.scala @@ -0,0 +1,52 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ + +package scala.collection.generic + +/** The base trait of all builders. + * A builder lets one construct a collection incrementally, by adding elements + * to the builder with += and then converting to the required collection type with + * `result`. + */ +trait Builder[-Elem, +To, -From] extends Growable[Elem] { + + /** Adds a single element to the builder. + * @param elem The element to be added + */ + def +=(elem: Elem) + + /** Clear the contents of this builder + */ + def clear() + + /** Returns collection resulting from this builder. The buffer's contents are undefined afterwards. + */ + def result(): To + + /** Give a hint how many elements are expected to be added + * when the next `result` is called. + */ + def sizeHint(size: Int) {} + + /** Create a new builder which is the same as the current builder except that + * a given function is applied to the current builder's result. + * @param f the function to apply to the builder's result + */ + def mapResult[NewTo](f: To => NewTo): Builder[Elem, NewTo, From] = + new Builder[Elem, NewTo, From] with Proxy { + val self = Builder.this + def +=(x: Elem) = self += x + def clear() = self.clear() + override def ++=(xs: Iterator[Elem]) = self ++= xs + override def ++=(xs: Traversible[Elem]) = self ++= xs + def result: NewTo = f(self.result) + } +} + diff --git a/src/library/scalax/collection/Set.scala b/src/library/scala/collection/generic/BuilderFactory.scala index a7234d0261..40bee09e43 100644 --- a/src/library/scalax/collection/Set.scala +++ b/src/library/scala/collection/generic/BuilderFactory.scala @@ -6,19 +6,14 @@ ** |/ ** \* */ -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ +// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ -package scalax.collection +package scala.collection.generic -import generic._ - -trait Set[A] extends SetTemplate[Set, A] - -/* Factory object for `Set` class */ -object Set extends IterableFactory[Set] { - /** The empty set */ - def apply[A](args: A*): Set[A] = null // !!! +/** A base class for builder factories + */ +trait BuilderFactory[-Elem, +To, -From] { + /** Creates a new builder */ + def apply(from: From): Builder[Elem, To, From] } - - diff --git a/src/library/scalax/collection/generic/Cloneable.scala b/src/library/scala/collection/generic/Cloneable.scala index acf9a16686..bc26da9069 100644..100755 --- a/src/library/scalax/collection/generic/Cloneable.scala +++ b/src/library/scala/collection/generic/Cloneable.scala @@ -9,11 +9,11 @@ // $Id: CloneableCollection.scala 16893 2009-01-13 13:09:22Z cunei $ -package scalax.collection.generic +package scala.collection.generic /** A trait for cloneable collections. */ @cloneable -trait Cloneable[A <: AnyRef] { +trait Cloneable[+A <: AnyRef] { override def clone(): A = super.clone().asInstanceOf[A] } diff --git a/src/library/scala/collection/generic/DoubleLinkedListTemplate.scala b/src/library/scala/collection/generic/DoubleLinkedListTemplate.scala new file mode 100755 index 0000000000..c86717f517 --- /dev/null +++ b/src/library/scala/collection/generic/DoubleLinkedListTemplate.scala @@ -0,0 +1,47 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: DoubleLinkedList.scala 16893 2009-01-13 13:09:22Z cunei $ + + +package scala.collection.generic + +/** This extensible class may be used as a basis for implementing double + * linked lists. Type variable <code>A</code> refers to the element type + * of the list, type variable <code>This</code> is used to model self + * types of linked lists. + * + * @author Matthias Zenger + * @version 1.0, 08/07/2003 + */ +trait DoubleLinkedListTemplate[A, This >: Null <: LinearSequence[A] with DoubleLinkedListTemplate[A, This]] extends LinkedListTemplate[A, This] { self => + + var prev: This = _ + + override def append(that: This): Unit = + if (next eq null) { + next = that + if (that ne null) that.prev = thisCollection + } else + next.append(that) + + override def insert(that: This): Unit = if (that ne null) { + that.append(next) + next = that + that.prev = thisCollection + } + + def remove() { + if (next ne null) + next.prev = prev + if (prev ne null) + prev.next = next + prev = null + next = null + } +} diff --git a/src/library/scala/collection/generic/GenericSequenceFactory.scala.disabled b/src/library/scala/collection/generic/GenericSequenceFactory.scala.disabled new file mode 100755 index 0000000000..70451741f8 --- /dev/null +++ b/src/library/scala/collection/generic/GenericSequenceFactory.scala.disabled @@ -0,0 +1,15 @@ +package scala.collection.generic + +/** A template for companion objects of Sequence and subclasses thereof. + */ +abstract class GenericSequenceFactory extends GenericTraversibleFactory { + + type Coll <: Sequence[_] + + /** This method is called in a pattern match { case Sequence(...) => }. + * + * @param x the selector value + * @return sequence wrapped in an option, if this is a Sequence, otherwise none + */ + def unapplySeq[A](x: Coll with Sequence[A]): Some[Coll with Sequence[A]] = Some(x) +} diff --git a/src/library/scala/collection/generic/GenericTraversibleFactory.scala.disabled b/src/library/scala/collection/generic/GenericTraversibleFactory.scala.disabled new file mode 100755 index 0000000000..dece49de37 --- /dev/null +++ b/src/library/scala/collection/generic/GenericTraversibleFactory.scala.disabled @@ -0,0 +1,186 @@ +package scala.collection.generic + +/** A template for companion objects of Traversible and subclasses thereof. + */ +abstract class GenericTraversibleFactory { + + type Coll <: Traversible[_] + + /** The empty iterable of type CC */ + def empty[A, That](implicit bf: Coll => Builder[A, That, Coll]): That = apply[A, That]() + + /** Creates an iterable of type CC with specified elements */ + def apply[A, That](args: A*)(implicit bf: Coll => Builder[A, That, Coll]): That = { + val b = bf(thisCollection) + b ++= Iterable.fromOld(args) + b.result + } + + /** Concatenate all the argument lists into a single list. + * + * @param xss the lists that are to be concatenated + * @return the concatenation of all the lists + */ + def concat[A, That](xss: Traversible[A]*)(implicit bf: Coll => Builder[A, That, Coll]): That = { + val b = bf(thisCollection) + for (xs <- Iterable.fromOld(xss)) + b ++= xs + b.result + } + + /** An iterable that contains the results of some element computation a number of times. + * @param n the number of elements returned + * @param elem the element computation + */ + def fill[A, That](n: Int)(elem: => A)(implicit bf: Coll => Builder[A, That, Coll]): That = { + val b = bf(thisCollection) + var i = 0 + while (i < n) { + b += elem + i += 1 + } + b.result + } + + /** A two-dimensional iterable that contains the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param elem the element computation + */ + def fill[A, C1, That](n1: Int, n2: Int)(elem: => A)(implicit b1: Builder[A, C1, Coll], b2: Builder[C1, That, Coll]): That = + tabulate(n1)(_ => fill(n2)(elem)) +/* + /** A three-dimensional iterable that contains the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param elem the element computation + */ + def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]]] = + tabulate(n1)(_ => fill(n2, n3)(elem)) + + /** A four-dimensional iterable that contains the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param elem the element computation + */ + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]]] = + tabulate(n1)(_ => fill(n2, n3, n4)(elem)) + + /** A five-dimensional iterable that contains the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param n5 the number of elements in the 5th dimension + * @param elem the element computation + */ + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]]] = + tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) +*/ + + /** An iterable containing values of a given function over a range of integer values starting from 0. + * @param n The number of elements in the iterable + * @param f The function computing element values + * @return An iterable consisting of elements `f(0), ..., f(n -1)` + */ + def tabulate[A, That](n: Int)(f: Int => A)(implicit bf: Coll => Builder[A, That, Coll]) = { + val b = bf(thisCollection) + var i = 0 + while (i < n) { + b += f(i) + i += 1 + } + b.result + } + + /** A two-dimensional iterable containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param f The function computing element values + */ + def tabulate[A, C1, That](n1: Int, n2: Int)(f: (Int, Int) => A)(implicit b1: Builder[A, C1, Coll], b2: Builder[C1, That, Coll]): That = + tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) + + /* + /** A three-dimensional iterable containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param f The function computing element values + */ + def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] = + tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) + + /** A four-dimensional iterable containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param f The function computing element values + */ + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]]] = + tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) + + /** A five-dimensional iterable containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param n5 the number of elements in the 5th dimension + * @param f The function computing element values + */ + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]]] = + tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) +*/ + + /** An iterable containing a sequence of increasing integers in a range. + * + * @param from the start value of the iterable + * @param end the end value of the iterable (the first value NOT returned) + * @return the iterable with values in range `start, start + 1, ..., end - 1` + * up to, but exclusding, `end`. + */ + def range[That](start: Int, end: Int)(implicit bf: Coll => Builder[Int, That, Coll]): That = + range(start, end, 1) + + /** An iterable containing equally spaced values in some integer interval. + + * @param start the start value of the iterable + * @param end the end value of the iterable (the first value NOT returned) + * @param step the increment value of the iterable (must be positive or negative) + * @return the iterable with values in `start, start + step, ...` up to, but excluding `end` + */ + def range[That](start: Int, end: Int, step: Int)(implicit bf: Coll => Builder[Int, That, Coll]): That = { + val b = bf(thisCollection) + if (step == 0) throw new IllegalArgumentException("zero step") + var i = start + while (if (step < 0) end < i else i < end) { + b += i + i += step + } + b.result + } + + /** An iterable containing repeated applications of a function to a start value. + * + * @param start the start value of the iterable + * @param len the number of elements returned by the iterable + * @param f the function that's repeatedly applied + * @return the iterable returning `len` values in the sequence `start, f(start), f(f(start)), ...` + */ + def iterate[That](start: Int, len: Int)(f: Int => Int)(implicit bf: Coll => Builder[Int, That, Coll]): That = { + val b = bf(thisCollection) + var acc = start + var i = 0 + while (i < len) { + b += acc + acc = f(acc) + i += 1 + } + b.result + } +} + diff --git a/src/library/scalax/collection/generic/Growable.scala b/src/library/scala/collection/generic/Growable.scala index 960384f9d0..7c4c52413b 100755 --- a/src/library/scalax/collection/generic/Growable.scala +++ b/src/library/scala/collection/generic/Growable.scala @@ -8,15 +8,16 @@ // $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ -package scalax.collection.generic +package scala.collection.generic -/** This class represents collections that can be augmented using a += operator. +/** This class represents collections that can be augmented using a `+=` operator + * and that can be cleared of all elements using the `clear` method. * * @autor Martin Odersky * @owner Martin Odersky * @version 2.8 */ -trait Growable[A] { +trait Growable[-A] { /** Adds a single element to this collection. * @@ -33,20 +34,20 @@ trait Growable[A] { def +=(elem1: A, elem2: A, elems: A*) { this += elem1 this += elem2 - this ++= elems.asInstanceOf[Iterable[A]] // !@! + this ++= Iterable.fromOld(elems) } /** Adds a number of elements provided by an iterator to this collection. * * @param iter the iterator. */ - def ++=(iter: collection.Iterator[A]) { iter foreach += } + def ++=(iter: Iterator[A]) { iter foreach += } /** Adds a number of elements provided by an iterable object to this collection. * * @param iter the iterable object. */ - def ++=(iter: collection.Iterable[A]) { iter foreach += } + def ++=(iter: Traversible[A]) { iter foreach += } /** Clears the collection contents. */ diff --git a/src/library/scala/collection/generic/ImmutableMapBuilder.scala b/src/library/scala/collection/generic/ImmutableMapBuilder.scala new file mode 100644 index 0000000000..028311e7e2 --- /dev/null +++ b/src/library/scala/collection/generic/ImmutableMapBuilder.scala @@ -0,0 +1,26 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ + +package scala.collection.generic + +// import collection.immutable.{List, Nil, ::} + +/** The canonical builder for collections that are addable, i.e. that support an efficient + method + * which adds an element to the collection. + * Collections are built from their empty element using this + method. + * @param empty The empty element of the collection. + */ +class ImmutableMapBuilder[A, B, Coll <: immutable.Map[A, B] with MapTemplate[A, B, Coll]](empty: Coll) +extends Builder[(A, B), Coll, Any] { + protected var elems: Coll = empty + def +=(x: (A, B)) { elems = (elems + x).asInstanceOf[Coll] } + def clear() { elems = empty } + def result: Coll = elems +} diff --git a/src/library/scala/collection/generic/ImmutableMapFactory.scala b/src/library/scala/collection/generic/ImmutableMapFactory.scala new file mode 100644 index 0000000000..54d4c90824 --- /dev/null +++ b/src/library/scala/collection/generic/ImmutableMapFactory.scala @@ -0,0 +1,16 @@ +package scala.collection.generic + +/** A template for companion objects of immutable.Map and subclasses thereof. + */ +abstract class ImmutableMapFactory[CC[A, +B] <: immutable.Map[A, B] with MapTemplate[A, B, CC[A, B]]] { + + def newBuilder[A, B]: Builder[(A, B), CC[A, B], Any] = new ImmutableMapBuilder[A, B, CC[A, B]](empty[A, B]) + + def empty[A, B]: CC[A, B] + + def apply[A, B](elems: (A, B)*): CC[A, B] = { + val b = newBuilder[A, B] + b ++= Iterable.fromOld(elems) + b.result + } +} diff --git a/src/library/scala/collection/generic/ImmutableMapTemplate.scala b/src/library/scala/collection/generic/ImmutableMapTemplate.scala new file mode 100755 index 0000000000..5600996ae8 --- /dev/null +++ b/src/library/scala/collection/generic/ImmutableMapTemplate.scala @@ -0,0 +1,50 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Map.scala 16884 2009-01-09 16:52:09Z cunei $ + + +package scala.collection.generic + +/** A generic template for immutable 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 elements: Iterator[(A, B)] + * def add(key: A, value: B): 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. + */ +trait ImmutableMapTemplate[A, +B, +This <: ImmutableMapTemplate[A, B, This] with immutable.Map[A, B]] + extends MapTemplate[A, B, This] { +self => + + override protected[this] def newBuilder: Builder[(A, B), This, Any] = new ImmutableMapBuilder[A, B, This](empty) + + /** This function transforms all the values of mappings contained + * in this map with function <code>f</code>. + * + * @param f A function over keys and values + * @return the updated map + */ + def transform[C, That](f: (A, B) => C)(implicit bf: BuilderFactory[(A, C), That, This]): That = { + val b = bf(thisCollection) + for ((key, value) <- this) b += ((key, f(key, value))) + b.result + } + + /** @deprecated use add instead */ + @deprecated def update[B1 >: B](key: A, value: B1): immutable.Map[A, B1] = add(key, value).asInstanceOf[immutable.Map[A, B1]] +} diff --git a/src/library/scalax/collection/generic/OrderedIterableForwarder.scala b/src/library/scala/collection/generic/IterableForwarder.scala index 643f31d861..f783f8c8fd 100755 --- a/src/library/scalax/collection/generic/OrderedIterableForwarder.scala +++ b/src/library/scala/collection/generic/IterableForwarder.scala @@ -9,29 +9,30 @@ // $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ -package scalax.collection.generic +package scala.collection.generic + +import collection.mutable.Buffer /** This trait implements a forwarder for iterable objects. It forwards * all calls to a different iterable object, except for * * - toString, hashCode, equals, stringPrefix * - newBuilder, view - * - all calls creating a new iterable object of the same kind + * - all calls creating a new iterable objetc of the same kind * * The above methods are forwarded by subclass IterableProxy * * @author Martin Odersky * @version 2.8 */ -trait OrderedIterableForwarder[+A] extends OrderedIterable[A] with IterableForwarder[A] { +trait IterableForwarder[+A] extends Iterable[A] with TraversibleForwarder[A] { /** The iterable object to which calls are forwarded */ - protected def underlying: OrderedIterable[A] + protected def underlying: Iterable[A] // Iterable delegates // Iterable methods could be printed by cat IterableTemplate.scala | sed -n '/trait Iterable/,$ p' | egrep '^ (override )?def' - override def last: A = underlying.last - override def lastOption: Option[A] = underlying.lastOption - override def sameElements[B >: A](that: OrderedIterable[B]): Boolean = underlying.sameElements(that) + override def elements = underlying.elements + override def sameElements[B >: A](that: Iterable[B]): Boolean = underlying.sameElements(that) } diff --git a/src/library/scala/collection/generic/IterableProxyTemplate.scala b/src/library/scala/collection/generic/IterableProxyTemplate.scala new file mode 100644 index 0000000000..577bfc24da --- /dev/null +++ b/src/library/scala/collection/generic/IterableProxyTemplate.scala @@ -0,0 +1,32 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ + + +package scala.collection.generic + +import collection.mutable.Buffer + +// Methods could be printed by cat IterableTemplate.scala | egrep '^ (override )?def' + + +/** This trait implements a proxy for iterable objects. It forwards + * all calls to a different iterable object + * + * @author Martin Odersky + * @version 2.8 + */ +trait IterableProxyTemplate[+A, +This <: IterableTemplate[A, This] with Iterable[A]] extends IterableTemplate[A, This] with TraversibleProxyTemplate[A, This] { + override def elements: Iterator[A] = self.elements + override def takeRight(n: Int): This = self.takeRight(n) + override def dropRight(n: Int): This = self.dropRight(n) + override def sameElements[B >: A](that: Iterable[B]): Boolean = self.sameElements(that) + override def view = self.view + override def view(from: Int, until: Int) = self.view(from, until) +} diff --git a/src/library/scala/collection/generic/IterableTemplate.scala b/src/library/scala/collection/generic/IterableTemplate.scala new file mode 100755 index 0000000000..e0ec5426a9 --- /dev/null +++ b/src/library/scala/collection/generic/IterableTemplate.scala @@ -0,0 +1,186 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ + +package scala.collection.generic + +import util.control.Breaks._ +// import immutable.Stream // !!! + +/** A template trait for iterable collections. + * + * Collection classes mixing in this trait provide a method + * <code>elements</code> which returns an iterator over all the + * elements contained in the collection. They also provide a method `newBuilder` + * which creates a builder for collections of the same kind. + * + * This trait implements Traversible's `foreach` method by stepping through + * all elements. Subclasses of `Iterable` should re-implement `foreach` with + * something more efficient, if possible. + * + * This trait adds methods `elements`, `sameElements`, + * `takeRight`, `dropRight` to the methods inherited from trait `Traversible`. + * + * @author Martin Odersky + * @version 2.8 + */ +trait IterableTemplate[+A, +This <: IterableTemplate[A, This] with Iterable[A]] extends TraversibleTemplate[A, This] { self => + + /** Creates a new iterator over all elements contained in this + * iterable object. + * + * @return the new iterator + */ + def elements: Iterator[A] + + /** Apply a function <code>f</code> to all elements of this + * traversible object. + * + * @param f a function that is applied to every element. + * @note This method underlies the implementation of most other bulk operations. + * It should be overridden in concrete collection classes with efficient implementations. + */ + def foreach(f: A => Unit): Unit = elements.foreach(f) + + /** Is this collection empty? + */ + override def isEmpty: Boolean = !elements.hasNext + + /** Combines the elements of this iterable together using the binary + * function <code>f</code>, from right to left, and starting with + * the value <code>z</code>. + * + * @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 <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code> + * if the iterable is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>. + */ + override def foldRight[B](z: B)(op: (A, B) => B): B = + elements.foldRight(z)(op) + + /** Combines the elements of this iterable object together using the binary + * operator <code>op</code>, 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 + * + * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code> + * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., + * a<sub>n</sub></code>. + * + * @throws Predef.UnsupportedOperationException if the iterator is empty. + */ + override def reduceRight[B >: A](op: (A, B) => B): B = + elements.reduceRight(op) + + /** The iterable itself */ + override def toIterable: Iterable[A] = thisCollection + + /** The first element of this iterable. + * + * @note Might return different results for different runs, unless this iterable is ordered + * @throws Predef.NoSuchElementException if the iterable is empty. + */ + override def head: A = if (isEmpty) throw new NoSuchElementException else elements.next + + /** Returns the rightmost <code>n</code> elements from this iterable. + * + * @param n the number of elements to take + * @note Might return different results for different runs, unless this iterable is ordered + */ + def takeRight(n: Int): This = { + val b = newBuilder + val lead = elements drop n + var go = false + for (x <- this) { + if (lead.hasNext) lead.next + else go = true + if (go) b += x + } + b.result + } + + /** Returns the iterable wihtout its rightmost <code>n</code> elements. + * + * @param n the number of elements to take + * @note Might return different results for different runs, unless this iterable is ordered + */ + def dropRight(n: Int): This = { + val b = newBuilder + val lead = elements drop n + breakable { + for (x <- this) { + if (!lead.hasNext) break + lead.next + b += x + } + } + b.result + } + + /** Checks if the other iterable object contains the same elements as this one. + * + * @note will not terminate for infinite-sized iterables. + * @param that the other iterable + * @return true, iff both iterables contain the same elements. + * @note Might return different results for different runs, unless this iterable is ordered + */ + def sameElements[B >: A](that: Iterable[B]): Boolean = { + val these = this.elements + val those = that.elements + while (these.hasNext && those.hasNext && these.next() == those.next()) {} + !these.hasNext && !those.hasNext + } + + /** Returns a stream with all elements in this traversible object. + */ + override def toStream: Stream[A] = elements.toStream + + /** Creates a view of this iterable @see IterableView + */ + override def view = new IterableView[A, This] { + protected lazy val underlying = self.thisCollection + override def elements = self.elements + } + + /** 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) + + /** @deprecated use head instead */ + @deprecated def first: A = head + + /** @deprecated use headOption instead + * <code>None</code> if traversible is empty. + */ + @deprecated def firstOption: Option[A] = headOption + + /** @deprecated use toSequence instead + */ + @deprecated def toSeq: Sequence[A] = toSequence + + /** + * returns a projection that can be used to call non-strict <code>filter</code>, + * <code>map</code>, and <code>flatMap</code> methods that build projections + * of the collection. + * @deprecated use view instead + */ + @deprecated def projection = view +} diff --git a/src/library/scalax/collection/immutable/EmptyMap.scala b/src/library/scala/collection/generic/IterableView.scala index c04d988f08..ab36b4550e 100644..100755 --- a/src/library/scalax/collection/immutable/EmptyMap.scala +++ b/src/library/scala/collection/generic/IterableView.scala @@ -5,30 +5,18 @@ ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ +package scala.collection.generic -// $Id: EmptyMap.scala 16893 2009-01-13 13:09:22Z cunei $ +import Math.MAX_INT +import TraversibleView.NoBuilder - - -package scalax.collection.immutable - -/** This class implements empty immutable maps - * @author Martin Oderskty - * @version 1.0, 019/01/2007 +/** A base class for views of Iterables. + * @author Martin Odersky + * @version 2.8 */ -@serializable -class EmptyMap[A, B] extends Map[A, B] { - - def size: Int = 0 - - def get(key: A): Option[B] = None +trait IterableView[+A, +Coll <: Iterable[_]] extends IterableViewTemplate[A, Coll, IterableView[A, Coll]] - def elements: Iterator[(A, B)] = Iterator.empty - - def update (key: A, value: B): Map[A, B] = new Map1(key, value) - - def - (key: A): Map[A, B] = this +object IterableView { + type Coll = TraversibleView[_, _] + implicit def builderFactory[A]: BuilderFactory[A, IterableView[A, Iterable[_]], Coll] = new BuilderFactory[A, IterableView[A, Iterable[_]], Coll] { def apply(from: Coll) = new NoBuilder } } - - - diff --git a/src/library/scala/collection/generic/IterableViewTemplate.scala b/src/library/scala/collection/generic/IterableViewTemplate.scala new file mode 100755 index 0000000000..99b6e23a1a --- /dev/null +++ b/src/library/scala/collection/generic/IterableViewTemplate.scala @@ -0,0 +1,63 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.collection.generic + +import Math.MAX_INT +import TraversibleView.NoBuilder + +/** A base class for views of Iterables. + * @author Martin Odersky + * @version 2.8 + */ +trait IterableViewTemplate[+A, + +Coll <: Iterable[_], + +This <: IterableView[A, Coll] with IterableViewTemplate[A, Coll, This]] +extends Iterable[A] with IterableTemplate[A, This] with TraversibleView[A, Coll] with TraversibleViewTemplate[A, Coll, This] +{ self => + + trait Transformed[+B] extends IterableView[B, Coll] with super.Transformed[B] + + trait Sliced extends Transformed[A] with super.Sliced { + override def elements = self.elements slice (from, until) + } + + trait Mapped[B] extends Transformed[B] with super.Mapped[B] { + override def elements = self.elements map mapping + } + + trait FlatMapped[B] extends Transformed[B] with super.FlatMapped[B] { + override def elements = self.elements flatMap (mapping(_).toIterable.elements) + } + + trait Appended[B >: A] extends Transformed[B] with super.Appended[B] { + override def elements = self.elements ++ rest.toIterable.elements + } + + trait Filtered extends Transformed[A] with super.Filtered { + override def elements = self.elements filter pred + } + + trait TakenWhile extends Transformed[A] with super.TakenWhile { + override def elements = self.elements takeWhile pred + } + + trait DroppedWhile extends Transformed[A] with super.DroppedWhile { + override def elements = self.elements dropWhile pred + } + + /** Boilerplate method, to override in each subclass + * This method could be eliminated if Scala had virtual classes + */ + protected override def newAppended[B >: A](that: Traversible[B]): Transformed[B] = new Appended[B] { val rest = that } + protected override def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f } + protected override def newFlatMapped[B](f: A => Traversible[B]): Transformed[B] = new FlatMapped[B] { val mapping = f } + protected override def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p } + protected override def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until } + protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p } + protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p } +} diff --git a/src/library/scala/collection/generic/LazyBuilder.scala b/src/library/scala/collection/generic/LazyBuilder.scala new file mode 100755 index 0000000000..019827d5ad --- /dev/null +++ b/src/library/scala/collection/generic/LazyBuilder.scala @@ -0,0 +1,27 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ + +package scala.collection.generic + +// import immutable.{List, Nil, ::} +import mutable.ListBuffer + +/** A builder that constructs its result lazily. Iterators or iterables to + * be added to this builder with `++=` are not evaluated until `result` is called. + */ +abstract class LazyBuilder[Elem, +To, -From] extends Builder[Elem, To, From] { + /** The different segments of elements to be added to the builder, represented as iterators */ + protected var parts = new ListBuffer[Traversible[Elem]] + def +=(x: Elem) = { parts += List(x) } + override def ++=(xs: Iterator[Elem]) { parts += xs.toStream } + override def ++=(xs: Traversible[Elem]) { parts += xs } + def result(): To + def clear() { parts.clear() } +} diff --git a/src/library/scala/collection/generic/LinearSequenceTemplate.scala b/src/library/scala/collection/generic/LinearSequenceTemplate.scala new file mode 100755 index 0000000000..30c2b92382 --- /dev/null +++ b/src/library/scala/collection/generic/LinearSequenceTemplate.scala @@ -0,0 +1,372 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ + + +package scala.collection.generic + +import mutable.ListBuffer +// import immutable.{List, Nil, ::} +import generic._ +import util.control.Breaks._ + +/** Class <code>Linear[A]</code> represents linear sequences of elements. + * For such sequences `isEmpty`, `head` and `tail` are guaranteed to be + * efficient constant time (or near so) operations. + * It does not add any methods to Sequence but overrides several + * methods with optimized implementations. + * + * @author Martin Odersky + * @author Matthias Zenger + * @version 1.0, 16/07/2003 + */ +trait LinearSequenceTemplate[+A, +This <: LinearSequenceTemplate[A, This] with LinearSequence[A]] extends SequenceTemplate[A, This] { self => + + /** Abstract method to be implemented in a subclass */ + def isEmpty: Boolean + + /** Abstract method to be implemented in a subclass */ + def head: A + + /** Abstract method to be implemented in a subclass */ + def tail: This + + /** Returns the number of elements in the linear sequence. + */ + def length: Int = { + var these = self + var len = 0 + while (!these.isEmpty) { + len += 1 + these = these.tail + } + len + } + + /** Returns the <code>n</code>-th element of this linear sequence. The first element + * (head of the linear sequence) is at position 0. + * + * @param n index of the element to return + * @return the element at position <code>n</code> in this linear sequence. + * @throws Predef.NoSuchElementException if the linear sequence is too short. + */ + def apply(n: Int): A = drop(n).head + + /** Returns the elements in the sequence as an iterator + */ + override def elements: Iterator[A] = new Iterator[A] { + var these = self + def hasNext: Boolean = !these.isEmpty + def next: A = + if (hasNext) { + val result = these.head; these = these.tail; result + } else Iterator.empty.next + override def toList: List[A] = these.toList + } + + /** Apply the given function <code>f</code> to each element of this linear sequence + * (while respecting the order of the elements). + * + * @param f the treatment to apply to each element. + */ + override def foreach(f: A => Unit) { + var these = this + while (!these.isEmpty) { + f(these.head) + these = these.tail + } + } + + /** Tests if the predicate <code>p</code> is satisfied by all elements + * in this list. + * + * @param p the test predicate. + * @return <code>true</code> iff all elements of this list satisfy the + * predicate <code>p</code>. + */ + override def forall(p: A => Boolean): Boolean = { + var these = this + while (!these.isEmpty) { + if (!p(these.head)) return false + these = these.tail + } + true + } + + /** Tests the existence in this list of an element that satisfies the + * predicate <code>p</code>. + * + * @param p the test predicate. + * @return <code>true</code> iff there exists an element in this list that + * satisfies the predicate <code>p</code>. + */ + override def exists(p: A => Boolean): Boolean = { + var these = this + while (!these.isEmpty) { + if (p(these.head)) return true + these = these.tail + } + false + } + + /** Count the number of elements in the iterable which satisfy a predicate. + * + * @param p the predicate for which to count + * @return the number of elements satisfying the predicate <code>p</code>. + */ + override def count(p: A => Boolean): Int = { + var these = this + var cnt = 0 + while (!these.isEmpty) { + if (p(these.head)) cnt += 1 + these = these.tail + } + cnt + } + + /** Find and return the first element of the list satisfying a + * predicate, if any. + * + * @param p the predicate + * @return the first element in the list satisfying <code>p</code>, + * or <code>None</code> if none exists. + */ + override def find(p: A => Boolean): Option[A] = { + var these = this + while (!these.isEmpty) { + if (p(these.head)) return Some(these.head) + these = these.tail + } + None + } + + /** Combines the elements of this list together using the binary + * function <code>f</code>, from left to right, and starting with + * the value <code>z</code>. + * + * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...), + * a<sub>n</sub>)</code> if the list is + * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>. + */ + override def foldLeft[B](z: B)(f: (B, A) => B): B = { + var acc = z + var these = this + while (!these.isEmpty) { + acc = f(acc, these.head) + these = these.tail + } + acc + } + + /** Combines the elements of this list together using the binary + * function <code>f</code>, from right to left, and starting with + * the value <code>z</code>. + * + * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code> + * if the list is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>. + */ + override def foldRight[B](z: B)(f: (A, B) => B): B = + if (this.isEmpty) z + else f(head, tail.foldRight(z)(f)) + + /** Combines the elements of this list together using the binary + * operator <code>op</code>, from left to right + * @param op The operator to apply + * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code> + if the list has elements + * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>. + * @throws Predef.UnsupportedOperationException if the list is empty. + */ + override def reduceLeft[B >: A](f: (B, A) => B): B = + if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft") + else tail.foldLeft[B](head)(f) + + /** Combines the elements of this iterable object together using the binary + * operator <code>op</code>, from right to left + * @note Will not terminate for infinite-sized collections. + * @param op The operator to apply + * + * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code> + * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., + * a<sub>n</sub></code>. + * + * @throws Predef.UnsupportedOperationException if the iterator is empty. + */ + override def reduceRight[B >: A](op: (A, B) => B): B = + if (isEmpty) throw new UnsupportedOperationException("Nil.reduceRight") + else if (tail.isEmpty) head + else op(head, tail.reduceRight(op)) + + /** The last element of this linear sequence. + * + * @throws Predef.NoSuchElementException if the linear sequence is empty. + */ + override def last: A = { + if (isEmpty) throw new NoSuchElementException + var these = this + var nx = these.tail + while (!nx.isEmpty) { + these = nx + nx = nx.tail + } + these.head + } + + override def take(n: Int): This = { + val b = newBuilder + var i = 0 + var these = this + while (!these.isEmpty && i < n) { + i += 1 + b += these.head + these = these.tail + } + b.result + } + + override def drop(n: Int): This = { + var these: This = thisCollection + var count = n + while (!these.isEmpty && count > 0) { + these = these.tail + count -= 1 + } + these + } + + /** Returns the rightmost <code>n</code> elements from this iterable. + * @param n the number of elements to take + */ + override def dropRight(n: Int): This = { + val b = newBuilder + var these = this + var lead = this drop n + while (!lead.isEmpty) { + b += these.head + these = these.tail + lead = lead.tail + } + b.result + } + + /** Returns a pair consisting of the longest prefix of the linear sequence whose + * elements all satisfy the given predicate, and the rest of the linear sequence. + * + * @param p the test predicate + */ + override def span(p: A => Boolean): (This, This) = { + var these: This = thisCollection + val b = newBuilder + while (!these.isEmpty && p(these.head)) { + b += these.head + these = these.tail + } + (b.result, these) + } + + /** Returns true iff the other linear sequence contains the same elements as this one. + * + * @note will not terminate for two infinite-sized linear sequences. + * @param that the other linear sequence + */ + override def sameElements[B >: A](that: Iterable[B]): Boolean = that match { + case that1: LinearSequence[_] => + val these = this + val those = that1 + while (!these.isEmpty && !those.isEmpty && these.head == those.head) {} + these.isEmpty && those.isEmpty + case _ => super.sameElements(that) + } + + // Overridden methods from Sequence + + /** Result of comparing <code>length</code> with operand <code>len</code>. + * returns <code>x</code> where + * <code>x < 0</code> iff <code>this.length < len</code> + * <code>x == 0</code> iff <code>this.length == len</code> + * <code>x > 0</code> iff <code>this.length > len</code>. + */ + override def lengthCompare(len: Int): Int = { + var i = 0 + var these = self + while (!these.isEmpty && i <= len) { + i += 1 + these = these.tail + } + i - len + } + + /** Is this partial function defined for the index <code>x</code>? + */ + override def isDefinedAt(x: Int): Boolean = x >= 0 && lengthCompare(x) > 0 + + /** 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 + */ + override def segmentLength(p: A => Boolean, from: Int): Int = { + var i = 0 + var these = this drop from + while (!these.isEmpty && p(these.head)) { + i += 1 + these = these.tail + } + i + } + + /** Returns index of the first element starting from a start index + * satisying a predicate, or -1, if none exists. + * + * @note may not terminate for infinite-sized linear sequences. + * @param p the predicate + * @param from the start index + */ + override def indexWhere(p: A => Boolean, from: Int): Int = { + var i = from + var these = this drop from + while (!these.isEmpty && !p(these.head)) { + i += 1 + these = these.tail + } + if (these.isEmpty) -1 else i + } + + /** Returns index of the last element satisying a predicate, or -1, if none exists. + * + * @param p the predicate + * @return the index of the last element satisfying <code>p</code>, + * or -1 if such an element does not exist + */ + override def lastIndexWhere(p: A => Boolean, end: Int): Int = { + var i = 0 + var these = this + var last = -1 + while (!these.isEmpty && i <= end) { + if (p(these.head)) last = i + these = these.tail + i += 1 + } + last + } + + override def equals(that: Any): Boolean = that match { + case that1: LinearSequence[a] => + var these = this + var those = that1 + while (!these.isEmpty && !those.isEmpty && these.head == those.head) { + these = these.tail + those = those.tail + } + these.isEmpty && those.isEmpty + case _ => + super.equals(that) + } +} diff --git a/src/library/scala/collection/generic/LinkedListTemplate.scala b/src/library/scala/collection/generic/LinkedListTemplate.scala new file mode 100755 index 0000000000..4abb6ceffb --- /dev/null +++ b/src/library/scala/collection/generic/LinkedListTemplate.scala @@ -0,0 +1,89 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: SingleLinkedList.scala 16893 2009-01-13 13:09:22Z cunei $ + + +package scala.collection.generic + +/** This extensible class may be used as a basis for implementing linked + * list. Type variable <code>A</code> refers to the element type of the + * list, type variable <code>This</code> is used to model self types of + * linked lists. + * !!! todo: integrate with LinearSequence, need to drop null then. + * @author Matthias Zenger + * @author Martin Odersky + * @version 2.8 + */ +trait LinkedListTemplate[A, This >: Null <: Sequence[A] with LinkedListTemplate[A, This]] extends SequenceTemplate[A, This] { self => + + var elem: A = _ + var next: This = _ + + override def isEmpty = false + + override def length: Int = 1 + (if (next eq null) 0 else next.length) + + override def head: A = elem + + override def tail: This = next + + def append(that: This): Unit = + if (next eq null) next = that else next.append(that) + + def insert(that: This): Unit = if (that ne null) { + that.append(next) + next = that + } + + override def drop(n: Int): This = { + var i = 0 + var these: This = thisCollection + while (i < n && (these ne null)) { + these = these.next.asInstanceOf[This] // !!! concrete overrides abstract problem + i += 1 + } + these + } + + override def apply(n: Int): A = { + val loc = drop(n) + if (loc ne null) loc.elem + else throw new IndexOutOfBoundsException(n.toString) + } + + def update(n: Int, x: A) { + val loc = drop(n) + if (loc ne null) loc.elem = x + else throw new IndexOutOfBoundsException(n.toString) + } + + def get(n: Int): Option[A] = { + val loc = drop(n) + if (loc ne null) Some(loc.elem) + else None + } + + override def elements: Iterator[A] = new Iterator[A] { + var elems = self + def hasNext = (elems ne null) + def next = { + val res = elems.elem + elems = elems.next + res; + } + } + + override def foreach(f: A => Unit): Unit = { + var these = this + while (these ne null) { + f(these.elem); + these = these.next + } + } +} diff --git a/src/library/scalax/collection/generic/MapTemplate.scala b/src/library/scala/collection/generic/MapTemplate.scala index 6d1a9e3c93..4be5fb2fb9 100755 --- a/src/library/scalax/collection/generic/MapTemplate.scala +++ b/src/library/scala/collection/generic/MapTemplate.scala @@ -9,53 +9,39 @@ // $Id: Map.scala 16884 2009-01-09 16:52:09Z cunei $ -package scalax.collection.generic - -import collection.immutable.Set -import collection.mutable.ArrayBuffer -import annotation.unchecked.uncheckedVariance - -/** <p> -* A map is a collection that maps each key to one or zero values. - * </p> - * <p> - * This trait provides a limited interface, only allowing reading of elements. - * There are two extensions of this trait, in packages - * <code><a href="mutable$content.html" target="contentFrame"> - * scala.collection.mutable</a></code> - * and <code><a href="immutable$content.html" target="contentFrame"> - * scala.collection.immutable</a></code>, which provide functionality for - * adding new key/value mappings to a map. The trait in the first package is - * for maps that are modified destructively, whereas the trait in - * the second package is for immutable maps which create a new map - * when something is added or removed from them. - * </p> +package scala.collection.generic + +/** 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 elements: Iterator[(A, B)] + * def add[B1 >: B](key: A, value: 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 * - * @author Matthias Zenger - * @author Martin Odersky - * @version 1.2, 31/12/2006 + * It is also good idea to override methods foreach and size for efficiency. */ -trait MapTemplate[A, B, +CC[A1, B1] <: Map[A1, B1] with MapTemplate[A1, B1, CC]] +trait MapTemplate[A, +B, +This <: MapTemplate[A, B, This] with Map[A, B]] extends PartialFunction[A, B] - with SizedIterable[(A, B)] - with Addable[CC[A, B], (A, B)] - with Subtractable[CC[A, B], A] { -self: CC[A, B] => + with IterableTemplate[(A, B), This] + with Subtractable[A, This] { +self => - def newBuilder[B]: Builder[SizedIterable, B] = new ArrayBuffer[B] +// import immutable.{Set, FlexSet} - override def thisCC: CC[A, B] = this + def empty: This - /** This method returns a new map instance of the same class - * mapping keys of the same type to values of type <code>C</code>. - */ - def empty[C]: CC[A, C] - - /** Compute the number of key-to-value mappings. + /** Is this an empty map? * - * @return the number of mappings + * @return <code>true</code> iff the map is empty. */ - def size: Int + override def isEmpty: Boolean = size == 0 /** Check if this map maps <code>key</code> to a value and return the * value if it exists. @@ -68,17 +54,10 @@ self: CC[A, B] => /** Check if this map maps <code>key</code> to a value. * Return that value if it exists, otherwise return <code>default</code>. */ - def getOrElse[B2 >: B](key: A, default: => B2): B2 = - get(key) match { - case Some(v) => v - case None => default - } - - /** Is this an empty map? - * - * @return <code>true</code> iff the map is empty. - */ - override def isEmpty: Boolean = size == 0 + def getOrElse[B1 >: B](key: A, default: => B1): B1 = get(key) match { + case Some(v) => v + case None => default + } /** Retrieve the value which is associated with the given key. This * method throws an exception if there is no mapping from the given @@ -119,17 +98,19 @@ self: CC[A, B] => def next = iter.next._1 } - /** @return the keys of this map as a set. - */ - def keySet: Set[A] = new Set[A] { - def size = self.size + protected class DefaultKeySet extends Set[A] { def contains(key : A) = self.contains(key) def elements = self.elements.map(_._1) - def + (elem: A): Set[A] = immutable.Set[A]() ++ this + elem - def - (elem: A): Set[A] = immutable.Set[A]() ++ this - elem - override def newBuilder[B]: Builder[Set, B] = Set.newBuilder[B] + def + (elem: A): Set[A] = (Set[A]() ++ this + elem).asInstanceOf[Set[A]] // !!! concrete overrides abstract problem + def - (elem: A): Set[A] = (Set[A]() ++ this - elem).asInstanceOf[Set[A]] // !!! concrete overrides abstract problem + override def size = self.size + override def foreach(f: A => Unit) = for ((k, v) <- self) f(k) } + /** @return the keys of this map as a set. + */ + def keySet: Set[A] = new DefaultKeySet + /** Creates an iterator for a contained values. * * @return an iterator over all values. @@ -140,13 +121,6 @@ self: CC[A, B] => def next = iter.next._2 } - /** Creates a string representation for this map. - * - * @return a string showing all mappings - */ - override def toString() = - elements.toList.map(kv => kv._1 + " -> " + kv._2).mkString(stringPrefix + "(", ", ", ")") - /** The default value for the map, returned when a key is not found * The method implemented here yields an error, * but it might be overridden in subclasses. @@ -157,47 +131,53 @@ self: CC[A, B] => def default(key: A): B = throw new NoSuchElementException("key not found: " + key) -/* - override def view: Map.View[A,B] = new Map.View[A, B] { - override def elements = self.elements - override def size = self.size - override def get(key: A): Option[B] = self.get(key) - } -*/ - def filterKeys(p: A => Boolean) = new MapView[CC, A, B] { - val origin = self + /** A map view consisting only of those key value pairs where the key satisfies a given + * predicate `p`. + */ + def filterKeys(p: A => Boolean) = new DefaultMap[A, B] { override def foreach(f: ((A, B)) => Unit): Unit = for (kv <- self) if (p(kv._1)) f(kv) def elements = self.elements.filter(kv => p(kv._1)) - def size = { var sz = 0; foreach(_ => sz += 1); sz } override def contains(key: A) = self.contains(key) && p(key) def get(key: A) = if (!p(key)) None else self.get(key) } - def mapElements[C](f: B => C) = new MapView[CC, A,C] { - val origin = self + /** A map view resulting from applying a given function `f` to each value. + */ + def mapValues[C](f: B => C) = new DefaultMap[A, C] { override def foreach(g: ((A, C)) => Unit): Unit = for ((k, v) <- self) g((k, f(v))) def elements = for ((k, v) <- self.elements) yield (k, f(v)) - def size = self.size + override def size = self.size override def contains(key: A) = self.contains(key) def get(key: A) = self.get(key).map(f) } - /** Defines the prefix of this object's <code>toString</code> representation. + /** @deprecated use mapValues instead */ - override def stringPrefix: String = "Map" + @deprecated def mapElements[C](f: B => C) = mapValues(f) /** Add a key/value pair to this map. * @param key the key * @param value the value * @return A new map with the new binding added to this map */ - def update (key: A, value: B): CC[A, B] + def add [B1 >: B](key: A, value: B1): Map[A, B1] /** Add a key/value pair to this map. - * @param kv the key/value pair. + * @param kv the key/value pair * @return A new map with the new binding added to this map */ - def + (kv: (A, B)): CC[A, B] = update(kv._1, kv._2) + def + [B1 >: B] (kv: (A, B1)): Map[A, B1] = add(kv._1, kv._2) + + /** Adds two or more elements to this collection and returns + * either the collection itself (if it is mutable), or a new collection + * with the added elements. + * + * @param elem1 the first element to add. + * @param elem2 the second element to add. + * @param elems the remaining elements to add. + */ + def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): Map[A, B1] = + (this + elem1 + elem2).++(collection.Iterable.fromOld(elems))(Map.builderFactory) /** Remove a key from this map * @param key the key to be removed @@ -205,43 +185,58 @@ self: CC[A, B] => * it is returned unchanged. Otherwise, return a new map * without a binding for <code>key</code> */ - def - (key: A): CC[A, B] + def - (key: A): This - /** This function transforms all the values of mappings contained - * in this map with function <code>f</code>. - * - * @param f A function over keys and values - * @return the updated map - */ - def transform[C](f: (A, B) => C): CC[A, C] = { - var res = empty[C] - for ((key, value) <- this) res += ((key, f(key, value))) - res - } - - /** Builds a new map with all key/value pairs of this map - * for which the predicate <code>p</code> returns <code>true</code>. + /** Removes all the mappings for which the predicate + * <code>p</code> returns <code>true</code>. * * @param p A predicate over key-value pairs * @return the updated map */ - override def filter(p: ((A, B)) => Boolean): CC[A, B] = { - var res = empty[B] + override def remove(p: ((A, B)) => Boolean): This = { + var res: This = thisCollection for (kv <- this) - if (p(kv)) res += kv + if (p(kv)) res = (res - kv._1).asInstanceOf[This] // !!! concrete overrides abstract problem res } - /** Removes all the mappings for which the predicate - * <code>p</code> returns <code>false</code>. + /** Creates a string representation for this map. * - * @param p A predicate over key-value pairs - * @return the updated map + * @return a string showing all mappings */ - override def remove(p: ((A, B)) => Boolean): CC[A, B] = { - var res = this - for (kv <- this) - if (!p(kv)) res -= kv._1 - res + override def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = + elements.map { case (k, v) => k+" -> "+v }.addString(b, start, sep, end) + + /** Compares two maps structurally; i.e. checks if all mappings + * contained in this map are also contained in the other map, + * and vice versa. + * + * @param that the other map + * @return <code>true</code> iff both maps contain exactly the + * same mappings. + */ + override def equals(that: Any): Boolean = that match { + case other: Map[a, b] => + if (this.size == other.size) + try { // can we find a safer way to do this? + this forall { + case (key, value) => other.get(key.asInstanceOf[a]) match { + case None => false + case Some(otherval) => value == otherval + } + } + } catch { + case ex: ClassCastException => false + } + else false + case _ => false } + + /** Defines the prefix of this object's <code>toString</code> representation. + */ + override def stringPrefix: String = "Map" + + /** Need to override string, so that it's not the Function1's string that gets mixed in. + */ + override def toString = super[IterableTemplate].toString } diff --git a/src/library/scala/collection/generic/MutableMapBuilder.scala b/src/library/scala/collection/generic/MutableMapBuilder.scala new file mode 100644 index 0000000000..04b3066bdb --- /dev/null +++ b/src/library/scala/collection/generic/MutableMapBuilder.scala @@ -0,0 +1,26 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ + +package scala.collection.generic + +// import collection.immutable.{List, Nil, ::} + +/** The canonical builder for collections that are addable, i.e. that support an efficient + method + * which adds an element to the collection. + * Collections are built from their empty element using this + method. + * @param empty The empty element of the collection. + */ +class MutableMapBuilder[A, B, Coll <: mutable.Map[A, B] with MapTemplate[A, B, Coll]](empty: Coll) +extends Builder[(A, B), Coll, Any] { + protected var elems: Coll = empty + def +=(x: (A, B)) { elems += x } + def clear() { elems = empty } + def result: Coll = elems +} diff --git a/src/library/scala/collection/generic/MutableMapFactory.scala b/src/library/scala/collection/generic/MutableMapFactory.scala new file mode 100644 index 0000000000..9c15d5ceec --- /dev/null +++ b/src/library/scala/collection/generic/MutableMapFactory.scala @@ -0,0 +1,16 @@ +package scala.collection.generic + +/** A template for companion objects of mutable.Map and subclasses thereof. + */ +abstract class MutableMapFactory[CC[A, B] <: mutable.Map[A, B] with MutableMapTemplate[A, B, CC[A, B]]] { + + def newBuilder[A, B]: Builder[(A, B), CC[A, B], Any] = new MutableMapBuilder(empty[A, B]) + + def empty[A, B]: CC[A, B] + + def apply[A, B](elems: (A, B)*): CC[A, B] = { + val b = newBuilder[A, B] + b ++= Iterable.fromOld(elems) + b.result + } +} diff --git a/src/library/scala/collection/generic/MutableMapTemplate.scala b/src/library/scala/collection/generic/MutableMapTemplate.scala new file mode 100644 index 0000000000..3a5801c1df --- /dev/null +++ b/src/library/scala/collection/generic/MutableMapTemplate.scala @@ -0,0 +1,173 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Map.scala 16884 2009-01-09 16:52:09Z cunei $ + + +package scala.collection.generic + +/** 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 elements: Iterator[(A, B)] + * def update(key: A, value: B) + * 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. + */ +trait MutableMapTemplate[A, B, +This <: MutableMapTemplate[A, B, This] with mutable.Map[A, B]] + extends MapTemplate[A, B, This] + with Builder[(A, B), This, Any] + with Growable[(A, B)] + with Shrinkable[A] + with Cloneable[This] +{ self => + + override protected[this] def newBuilder: Builder[(A, B), This, Any] = new MutableMapBuilder[A, B, This](empty.asInstanceOf[This]) // !!! concrete overrides abstract problem + + /** This method allows one to add a new mapping from <code>key</code> + * to <code>value</code> to the map. If the map already contains a + * mapping for <code>key</code>, it will be overridden by this + * function. + * + * @param key The key to update + * @param value The new value + */ + def update(key: A, value: B) + + /** Add a key/vaue pair to this map, and return the map itself + */ + def add(key: A, value: B): this.type = { update(key, value); this } + + /** Map <code>key</code> to <code>elem</code> in this map and return the element + * that the key was previously mapped to (if any). + */ + def put(key: A, elem: B): Option[B] = { + val ret = get(key) + this(key) = elem + ret + } + + /** Add a key/value pair to this map. + * @param kv the key/value pair. + */ + def += (kv: (A, B)) { update(kv._1, kv._2) } + + /** A default implementation of addition where the value is not of the same type as + * the current map value type. This will always create a new immutable Map. + */ + def add[B1 >: B](key: A, value: B1): collection.Map[A, B1] = + Map[A, B1]() ++ thisCollection + ((key, value)) + + /** Adds a single element to this collection and returns + * either the collection itself (if it is mutable), or a new collection + * with the added element. + * + * @param elem the element to add. + */ + //override + def +(kv: (A, B)): this.type = add(kv._1, kv._2) + + /** Adds two or more elements to this collection and returns + * either the collection itself (if it is mutable), or a new collection + * with the added elements. + * + * @param elem1 the first element to add. + * @param elem2 the second element to add. + * @param elems the remaining elements to add. + */ + //override + def +(elem1: (A, B), elem2: (A, B), elems: (A, B)*): this.type = + this + elem1 + elem2 ++ Iterable.fromOld(elems) + + /** Adds a number of elements provided by an iterable object + * via its <code>elements</code> method and returns + * either the collection itself (if it is mutable), or a new collection + * with the added elements. + * + * @param iter the iterable object. + */ + //override + def ++(iter: Traversible[(A, B)]): this.type = { (this /: iter) (_ + _); this } + + /** Adds a number of elements provided by an iterator + * via its <code>elements</code> method and returns + * either the collection itself (if it is mutable), or a new collection + * with the added elements. + * + * @param iter the iterator + */ + //override + def ++(iter: Iterator[(A, B)]): this.type = { (this /: iter) (_ + _); this } + + /** Remove a key from this map, noop if key is not presentg. + * @param key the key to be removed + */ + def -= (key: A) + + def -(key: A): This = { -=(key); thisCollection } + + def removeKey(key: A): Option[B] = { + val ret = get(key) + this -= key + ret + } + + // todo: add other -'s + + /** Removes all elements from the set. After this operation is completed, + * the set will be empty. + */ + def clear() { for ((k, v) <- elements) -=(k) } + + /** Check if this map maps <code>key</code> to a value. + * Return that value if it exists, otherwise put <code>default</code> + * as that key's value and return it. + */ + def getOrElseUpdate(key: A, default: => B): B = + get(key) match { + case Some(v) => v + case None => val d = default; this(key) = d; d + } + + /** This function transforms all the values of mappings contained + * in this map with function <code>f</code>. + * + * @param f The transformation to apply + */ + def transform(f: (A, B) => B): this.type = { + elements foreach { + case (key, value) => update(key, f(key, value)) + } + this + } + + /** This method retains only those mappings for which the predicate + * <code>p</code> returns <code>true</code>. + * + * @param p The test predicate + * @deprecated cannot be type inferred because if retain in Iterable. + */ + def retain(p: (A, B) => Boolean): this.type = { + for ((k, v) <- this) if (!p(k, v)) -=(k) + this + } + + override def clone(): This = + empty ++ thisCollection + + /** The result when this map is used as a builder */ + def result: This = thisCollection +} diff --git a/src/library/scala/collection/generic/MutableVectorTemplate.scala b/src/library/scala/collection/generic/MutableVectorTemplate.scala new file mode 100755 index 0000000000..cfc65de9ec --- /dev/null +++ b/src/library/scala/collection/generic/MutableVectorTemplate.scala @@ -0,0 +1,38 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.collection.generic + +/** A subtrait of collection.Vector which represents sequences + * that can be mutated. + */ +trait MutableVectorTemplate[A, +This <: MutableVectorTemplate[A, This] with mutable.Vector[A]] extends VectorTemplate[A, This] { self => + + def update(idx: Int, elem: A) + + /** Creates a view of this iterable @see Iterable.View + */ + override def view = new MutableVectorView[A, This] { + protected lazy val underlying = self.thisCollection + override def elements = self.elements + override def length = self.length + override def apply(idx: Int) = self.apply(idx) + override def update(idx: Int, elem: A) = self.update(idx, elem) + } + + /** A sub-sequence 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 sequence, whereas `slice` produces a new sequence. + * + * @note view(from, to) is equivalent to view.slice(from, to) + */ + override def view(from: Int, until: Int) = view.slice(from, until) +} diff --git a/src/library/scala/collection/generic/MutableVectorView.scala b/src/library/scala/collection/generic/MutableVectorView.scala new file mode 100755 index 0000000000..4b7ece1dab --- /dev/null +++ b/src/library/scala/collection/generic/MutableVectorView.scala @@ -0,0 +1,26 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ + + +package scala.collection.generic + +import TraversibleView.NoBuilder + +/** A non-strict projection of an iterable. + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ +trait MutableVectorView[A, +Coll <: mutable.Vector[_]] extends MutableVectorViewTemplate[A, Coll, MutableVectorView[A, Coll]] + +object MutableVectorView { + type Coll = TraversibleView[_, _] + implicit def builderFactory[A]: BuilderFactory[A, MutableVectorView[A, mutable.Vector[_]], Coll] = new BuilderFactory[A, MutableVectorView[A, mutable.Vector[_]], Coll] { def apply(from: Coll) = new NoBuilder } +} diff --git a/src/library/scala/collection/generic/MutableVectorViewTemplate.scala b/src/library/scala/collection/generic/MutableVectorViewTemplate.scala new file mode 100755 index 0000000000..22b46472c7 --- /dev/null +++ b/src/library/scala/collection/generic/MutableVectorViewTemplate.scala @@ -0,0 +1,66 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ + + +package scala.collection.generic + +import TraversibleView.NoBuilder + +/** A non-strict projection of an iterable. + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ +trait MutableVectorViewTemplate[A, + +Coll <: mutable.Vector[_], + +This <: MutableVectorView[A, Coll] with MutableVectorViewTemplate[A, Coll, This]] + extends mutable.Vector[A] with MutableVectorTemplate[A, This] with VectorView[A, Coll] with VectorViewTemplate[A, Coll, This] +{ self => + + trait Transformed[B] extends MutableVectorView[B, Coll] with super.Transformed[B] { + def update(idx: Int, elem: B) + } + + trait Sliced extends Transformed[A] with super.Sliced { + override def update(idx: Int, elem: A) = + if (idx + from < until) self.update(idx + from, elem) + else throw new IndexOutOfBoundsException(idx.toString) + } + + trait Filtered extends Transformed[A] with super.Filtered { + override def update(idx: Int, elem: A) = self.update(index(idx), elem) + } + + trait TakenWhile extends Transformed[A] with super.TakenWhile { + override def update(idx: Int, elem: A) = + if (idx < len) self.update(idx, elem) + else throw new IndexOutOfBoundsException(idx.toString) + } + + trait DroppedWhile extends Transformed[A] with super.DroppedWhile { + override def update(idx: Int, elem: A) = + if (idx >= 0) self.update(idx + start, elem) + else throw new IndexOutOfBoundsException(idx.toString) + } + + trait Reversed extends Transformed[A] with super.Reversed { + override def update(idx: Int, elem: A) = self.update(length - 1 - idx, elem) + } + + /** Boilerplate method, to override in each subclass + * This method could be eliminated if Scala had virtual classes + */ + protected override def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p } + protected override def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until } + protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p } + protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p } + protected override def newReversed: Transformed[A] = new Reversed { } +} + diff --git a/src/library/scala/collection/Ranged.scala b/src/library/scala/collection/generic/Ranged.scala index 7bddb0c688..c0610ad893 100644 --- a/src/library/scala/collection/Ranged.scala +++ b/src/library/scala/collection/generic/Ranged.scala @@ -6,16 +6,16 @@ ** |/ ** \* */ -// $Id$ +// $Id: Ranged.scala 17537 2009-04-20 18:37:37Z odersky $ -package scala.collection +package scala.collection.generic /** Any collection (including maps) whose keys (or elements) are ordered. * - * @author Sean McDirmid + * @author martin Odersky + * @version 2.8 */ -trait Ranged[K, +A] extends Iterable[A] { - //protected type SortedSelf <: Ranged[K,A]; +trait Ranged[K, +This <: Ranged[K, This]] { /** Returns the first key of the collection. */ def firstKey: K @@ -36,19 +36,19 @@ trait Ranged[K, +A] extends Iterable[A] { * @param until The upper-bound (exclusive) of the ranged projection. * <code>None</code> if there is no upper bound. */ - def rangeImpl(from: Option[K], until: Option[K]): Ranged[K, A] + def rangeImpl(from: Option[K], until: Option[K]): This /** Creates a ranged projection of this collection with no upper-bound. * * @param from The lower-bound (inclusive) of the ranged projection. */ - def from(from: K) = rangeImpl(Some(from), None) + def from(from: K): This = rangeImpl(Some(from), None) /** Creates a ranged projection of this collection with no lower-bound. * * @param until The upper-bound (exclusive) of the ranged projection. */ - def until(until: K) = rangeImpl(None, Some(until)) + def until(until: K): This = rangeImpl(None, Some(until)) /** Creates a ranged projection of this collection with both a lower-bound * and an upper-bound. @@ -57,5 +57,5 @@ trait Ranged[K, +A] extends Iterable[A] { * @param until ... * @return ... */ - def range(from: K, until: K) = rangeImpl(Some(from), Some(until)) + def range(from: K, until: K): This = rangeImpl(Some(from), Some(until)) } diff --git a/src/library/scalax/collection/generic/SequenceFactory.scala b/src/library/scala/collection/generic/SequenceFactory.scala index 26818c49c9..cb2762c4d0 100755 --- a/src/library/scalax/collection/generic/SequenceFactory.scala +++ b/src/library/scala/collection/generic/SequenceFactory.scala @@ -1,6 +1,8 @@ -package scalax.collection.generic +package scala.collection.generic -trait SequenceFactory[CC[A] <: Sequence[A]] extends IterableFactory[CC] { +/** A template for companion objects of Sequence and subclasses thereof. + */ +abstract class SequenceFactory[CC[A] <: Sequence[A]] extends TraversibleFactory[CC] { /** This method is called in a pattern match { case Sequence(...) => }. * diff --git a/src/library/scalax/collection/generic/SequenceForwarder.scala b/src/library/scala/collection/generic/SequenceForwarder.scala index 63dca249b6..bf92128d41 100644..100755 --- a/src/library/scalax/collection/generic/SequenceForwarder.scala +++ b/src/library/scala/collection/generic/SequenceForwarder.scala @@ -9,14 +9,14 @@ // $Id: SeqProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ -package scalax.collection.generic +package scala.collection.generic /** This class implements a forwarder for sequences. It forwards * all calls to a different sequence object except for * * - toString, hashCode, equals, stringPrefix * - newBuilder, view, toSequence - * - all calls creating a new iterable objetc of the same kind + * - all calls creating a new sequence of the same kind * * The above methods are forwarded by subclass SequenceProxy * @@ -44,7 +44,7 @@ trait SequenceForwarder[+A] extends Sequence[A] with IterableForwarder[A] { override def reversedElements: Iterator[A] = underlying.reversedElements override def startsWith[B](that: Sequence[B], offset: Int): Boolean = underlying.startsWith(that, offset) override def endsWith[B](that: Sequence[B]): Boolean = underlying.endsWith(that) - override def indexOf[B >: A](that: Sequence[B]): Int = underlying.indexOf(that) + override def indexOfSeq[B >: A](that: Sequence[B]): Int = underlying.indexOfSeq(that) override def contains(elem: Any): Boolean = underlying.contains(elem) override def indices: Range = underlying.indices } diff --git a/src/library/scala/collection/generic/SequenceProxyTemplate.scala b/src/library/scala/collection/generic/SequenceProxyTemplate.scala new file mode 100644 index 0000000000..1854267ad8 --- /dev/null +++ b/src/library/scala/collection/generic/SequenceProxyTemplate.scala @@ -0,0 +1,59 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ + + +package scala.collection.generic + +import collection.mutable.Buffer + +// Methods could be printed by cat SequenceTemplate.scala | egrep '^ (override )?def' + + +/** This trait implements a proxy for iterable objects. It forwards + * all calls to a different iterable object + * + * @author Martin Odersky + * @version 2.8 + */ +trait SequenceProxyTemplate[+A, +This <: SequenceTemplate[A, This] with Sequence[A]] extends SequenceTemplate[A, This] with IterableProxyTemplate[A, This] { + override def length: Int = self.length + override def apply(idx: Int): A = self.apply(idx) + override def lengthCompare(len: Int): Int = self.lengthCompare(len) + override def isDefinedAt(x: Int): Boolean = self.isDefinedAt(x) + override def zip[A1 >: A, B, That](that: Sequence[B])(implicit bf: BuilderFactory[(A1, B), That, This]): That = self.zip[A1, B, That](that)(bf) + override def zipAll[B, A1 >: A, That](that: Sequence[B], thisElem: A1, thatElem: B)(implicit bf: BuilderFactory[(A1, B), That, This]): That = self.zipAll(that, thisElem, thatElem)(bf) + override def zipWithIndex[A1 >: A, That](implicit bf: BuilderFactory[(A1, Int), That, This]): That = self.zipWithIndex(bf) + override def segmentLength(p: A => Boolean, from: Int): Int = self.segmentLength(p, from) + override def prefixLength(p: A => Boolean) = self.prefixLength(p) + override def indexWhere(p: A => Boolean): Int = self.indexWhere(p) + override def indexWhere(p: A => Boolean, from: Int): Int = self.indexWhere(p, from) + override def indexOf[B >: A](elem: B): Int = self.indexOf(elem) + override def indexOf[B >: A](elem: B, from: Int): Int = self.indexOf(elem, from) + override def lastIndexOf[B >: A](elem: B): Int = self.lastIndexOf(elem) + override def lastIndexOf[B >: A](elem: B, end: Int): Int = self.lastIndexWhere(elem ==, end) + override def lastIndexWhere(p: A => Boolean): Int = self.lastIndexWhere(p, length - 1) + override def lastIndexWhere(p: A => Boolean, end: Int): Int = self.lastIndexWhere(p) + override def reverse: This = self.reverse + override def reversedElements: Iterator[A] = self.reversedElements + override def startsWith[B](that: Sequence[B], offset: Int): Boolean = self.startsWith(that, offset) + override def startsWith[B](that: Sequence[B]): Boolean = self.startsWith(that) + override def endsWith[B](that: Sequence[B]): Boolean = self.endsWith(that) + override def indexOfSeq[B >: A](that: Sequence[B]): Int = self.indexOfSeq(that) + override def contains(elem: Any): Boolean = self.contains(elem) + override def union[B >: A, That](that: Sequence[B])(implicit bf: BuilderFactory[B, That, This]): That = self.union(that)(bf) + override def diff[B >: A, That](that: Sequence[B]): This = self.diff(that) + override def intersect[B >: A, That](that: Sequence[B]): This = self.intersect(that) + override def removeDuplicates: This = self.removeDuplicates + override def patch[B >: A, That](from: Int, patch: Sequence[B], replaced: Int)(implicit bf: BuilderFactory[B, That, This]): That = self.patch(from, patch, replaced)(bf) + override def padTo[B >: A, That](len: Int, elem: B)(implicit bf: BuilderFactory[B, That, This]): That = self.padTo(len, elem)(bf) + override def indices: Range = self.indices + override def view = self.view + override def view(from: Int, until: Int) = self.view(from, until) +} diff --git a/src/library/scalax/collection/generic/SequenceTemplate.scala b/src/library/scala/collection/generic/SequenceTemplate.scala index 3407f63216..b1643a1a62 100755 --- a/src/library/scalax/collection/generic/SequenceTemplate.scala +++ b/src/library/scala/collection/generic/SequenceTemplate.scala @@ -9,15 +9,26 @@ // $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ -package scalax.collection.generic +package scala.collection.generic +import mutable.{ListBuffer, HashMap} +// import immutable.{List, Nil, ::} +import generic._ import util.control.Breaks._ -import scalax.collection.immutable.{List, Nil, ::} -import Sequence._ - -trait SequenceTemplate[+CC[/*+*/B] <: SequenceTemplate[CC, B] with Sequence[B], /*+*/A] extends PartialFunction[Int, A] with OrderedIterableTemplate[CC, A] { -self /*: CC[A]*/ => +/** Class <code>Sequence[A]</code> represents sequences of elements + * of type <code>A</code>. + * It adds the following methods to class Iterable: + * `length`, `lengthCompare`, `apply`, `isDefinedAt`, `segmentLength`, `prefixLengh`, + * `indexWhere`, `indexOf`, `lastIndexWhere`, `lastIndexOf`, `reverse`, `reversedElements`, + * `startsWith`, `endsWith`, `indexOfSeq`, , `zip`, `zipAll`, `zipWithIndex`. + * + * + * @author Martin Odersky + * @author Matthias Zenger + * @version 1.0, 16/07/2003 + */ +trait SequenceTemplate[+A, +This <: IterableTemplate[A, This] with Sequence[A]] extends IterableTemplate[A, This] { self => /** Returns the length of the sequence. * @@ -25,6 +36,10 @@ self /*: CC[A]*/ => */ def length: Int + /** Returns the elements at position `idx` + */ + def apply(idx: Int): A + /** Result of comparing <code>length</code> with operand <code>len</code>. * returns <code>x</code> where * <code>x < 0</code> iff <code>this.length < len</code> @@ -47,12 +62,71 @@ self /*: CC[A]*/ => } /** Should always be <code>length</code> */ - def size = length + override def size = length /** Is this partial function defined for the index <code>x</code>? */ def isDefinedAt(x: Int): Boolean = (x >= 0) && (x < length) + /** Returns an iterable formed from this iterable and another iterable + * by combining corresponding elements in pairs. + * If one of the two iterables is longer than the other, its remaining elements are ignored. + * @param that The iterable providing the second half of each result pair + */ + def zip[A1 >: A, B, That](that: Sequence[B])(implicit bf: BuilderFactory[(A1, B), That, This]): That = { + val b = bf(thisCollection) + val these = this.elements + val those = that.elements + while (these.hasNext && those.hasNext) + b += ((these.next, those.next)) + b.result + } + + /** Returns a iterable formed from this iterable and the specified iterable + * <code>that</code> by associating each element of the former with + * the element at the same position in the latter. + * + * @param that iterable <code>that</code> may have a different length + * as the self iterable. + * @param thisElem element <code>thisElem</code> is used to fill up the + * resulting iterable if the self iterable is shorter than + * <code>that</code> + * @param thatElem element <code>thatElem</code> is used to fill up the + * resulting iterable if <code>that</code> is shorter than + * the self iterable + * @return <code>Sequence((a<sub>0</sub>,b<sub>0</sub>), ..., + * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>), + * ..., {elem,b<sub>m</sub>})</code> + * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip + * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is + * invoked where <code>m > n</code>. + * + */ + def zipAll[B, A1 >: A, That](that: Sequence[B], thisElem: A1, thatElem: B)(implicit bf: BuilderFactory[(A1, B), That, This]): That = { + val b = bf(thisCollection) + val these = this.elements + val those = that.elements + while (these.hasNext && those.hasNext) + b += ((these.next, those.next)) + while (these.hasNext) + b += ((these.next, thatElem)) + while (those.hasNext) + b += ((thisElem, those.next)) + b.result + } + + /** Zips this iterable with its indices (startiong from 0). + */ + def zipWithIndex[A1 >: A, That](implicit bf: BuilderFactory[(A1, Int), That, This]): That = { + val b = bf(thisCollection) + var i = 0 + for (x <- this) { + b += ((x, i)) + i +=1 + } + b.result + } + /** 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. @@ -61,7 +135,7 @@ self /*: CC[A]*/ => */ def segmentLength(p: A => Boolean, from: Int): Int = { var result = 0 - var i = from + var i = 0 breakable { for (x <- this) { if (i >= from && !p(x)) { result = i - from; break } @@ -138,7 +212,7 @@ self /*: CC[A]*/ => * specified element, or -1 if the sequence does not contain * this element. */ - def lastIndexOf[B >: A](elem: B): Int = lastIndexOf(elem, length - 1) + def lastIndexOf[B >: A](elem: B): Int = lastIndexWhere(elem ==) /** Returns the index of the last * occurence of the specified element in this sequence @@ -148,12 +222,7 @@ self /*: CC[A]*/ => * @param elem element to search for. * @param end the end index */ - def lastIndexOf[B >: A](elem: B, end: Int): Int = { - var i = end - val it = reversedElements - while (it.hasNext && it.next != elem) i -= 1 - i - } + 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. * @@ -170,9 +239,9 @@ self /*: CC[A]*/ => * @param p the predicate */ def lastIndexWhere(p: A => Boolean, end: Int): Int = { - var i = end + var i = length - 1 val it = reversedElements - while (it.hasNext && (i > end || !p(it.next))) i -= 1 + while (it.hasNext && { val elem = it.next; (i > end || !p(elem)) }) i -= 1 i } @@ -183,11 +252,11 @@ self /*: CC[A]*/ => * If random access is inefficient for the given sequence implementation, * this operation should be overridden. */ - def reverse: CC[A] = { + def reverse: This = { var xs: List[A] = List() for (x <- this) xs = x :: xs - val b = newBuilder[A] + val b = newBuilder for (x <- xs) b += x b.result @@ -213,7 +282,9 @@ self /*: CC[A]*/ => def startsWith[B](that: Sequence[B], offset: Int): Boolean = { val i = elements.drop(offset) val j = that.elements - while (j.hasNext && i.hasNext && i.next == j.next) {} + while (j.hasNext && i.hasNext) { + if (i.next != j.next) return false + } !j.hasNext } @@ -222,8 +293,6 @@ self /*: CC[A]*/ => * * @return true if <code>that</code> is a prefix of <code>this</code>, * otherwise false - * - * @see Sequence.startsWith */ def startsWith[B](that: Sequence[B]): Boolean = startsWith(that, 0) @@ -241,12 +310,12 @@ self /*: CC[A]*/ => * index where <code>that</code> is contained * @see String.indexOf */ - def indexOf[B >: A](that: Sequence[B]): Int = { + def indexOfSeq[B >: A](that: Sequence[B]): Int = { var i = 0 - var s: Sequence[A] = thisCC + var s: Sequence[A] = thisCollection while (!s.isEmpty && !(s startsWith that)) { i += 1 - s = s drop 1 + s = s.tail } if (!s.isEmpty || that.isEmpty) i else -1 } @@ -260,56 +329,120 @@ self /*: CC[A]*/ => */ def contains(elem: Any): Boolean = exists (_ == elem) - /** Computes the union of this sequence and the given sequence - * <code>that</code>. + /** <p> + * Computes the multiset union of this sequence and the given sequence + * <code>that</code>. For example: + * </p><pre> + * <b>val</b> xs = List(1, 1, 2) + * <b>val</b> ys = List(1, 2, 2, 3) + * println(xs union ys) // prints "List(1, 1, 2, 1, 2, 2, 3)" + * println(ys union xs) // prints "List(1, 2, 2, 3, 1, 1, 2)" + * </pre> * * @param that the sequence of elements to add to the sequence. - * @return an sequence containing the elements of this - * sequence and those of the given sequence <code>that</code> - * which are not contained in this sequence. + * @return a sequence containing the elements of this + * sequence and those of the given sequence <code>that</code>. */ - def union[B >: A](that: Sequence[B]): CC[B] = this ++ (that diff thisCC) - - /** Computes the difference between this sequence and the given sequence - * <code>that</code>. + def union[B >: A, That](that: Sequence[B])(implicit bf: BuilderFactory[B, That, This]): That = + thisCollection ++ that + + /** <p> + * Computes the multiset difference between this sequence and the + * given sequence <code>that</code>. If an element appears more + * than once in both sequences, the difference contains <i>m</i> copies + * of that element, where <i>m</i> is the difference between the + * number of times the element appears in this sequence and the number + * of times it appears in <code>that</code>. For example: + * </p><pre> + * <b>val</b> xs = List(1, 1, 2) + * <b>val</b> ys = List(1, 2, 2, 3) + * println(xs diff ys) // prints "List(1)" + * println(xs -- ys) // prints "List()" + * </pre> * * @param that the sequence of elements to remove from this sequence. - * @return this sequence without the elements of the given sequence - * <code>that</code>. + * @return the sequence of elements contained only in this sequence plus + * <i>m</i> copies of each element present in both sequences, + * where <i>m</i> is defined as above. */ - def diff[B >: A](that: Sequence[B]): CC[A] = this remove (that contains _) + def diff[B >: A, That](that: Sequence[B]): This = { + val occ = occCounts(that) + val b = newBuilder + for (x <- this) + if (occ(x) == 0) b += x + else occ(x) -= 1 + b.result + } - /** Computes the intersection between this sequence and the given sequence - * <code>that</code>. + /** <p> + * Computes the multiset intersection between this sequence and the + * given sequence <code>that</code>; the intersection contains <i>m</i> + * copies of an element contained in both sequences, where <i>m</i> is + * the smaller of the number of times the element appears in this + * sequence or in <code>that</code>. For example: + * </p><pre> + * <b>val</b> xs = List(1, 1, 2) + * <b>val</b> ys = List(3, 2, 2, 1) + * println(xs intersect ys) // prints "List(1, 2)" + * println(ys intersect xs) // prints "List(2, 1)" + * </pre> * * @param that the sequence to intersect. * @return the sequence of elements contained both in this sequence and * in the given sequence <code>that</code>. */ - def intersect[B >: A](that: Sequence[B]): CC[A] = this filter(that contains _) + def intersect[B >: A, That](that: Sequence[B]): This = { + val occ = occCounts(that) + val b = newBuilder + for (x <- this) + if (occ(x) > 0) { + b += x + occ(x) -= 1 + } + b.result + } + + private def occCounts[B](seq: Sequence[B]): HashMap[B, Int] = { + val occ = new HashMap[B, Int] { override def default(k: B) = 0 } + for (y <- seq) occ(y) += 1 + occ + } /** Builds a new sequence from this sequence in which any duplicates (wrt to ==) removed. * Among duplicate elements, only the first one is retained in the result sequence */ - def removeDuplicates: CC[A] = { - val b = newBuilder[A] + def removeDuplicates: This = { + val b = newBuilder var seen = Set[A]() for (x <- this) { if (!(seen contains x)) { b += x - seen += x + seen = (seen + x) } } b.result } + /** A new sequence, consisting of all elements of current sequence + * except that `replaced` elements starting from `from` are replaced + * by `patch`. + */ + def patch[B >: A, That](from: Int, patch: Sequence[B], replaced: Int)(implicit bf: BuilderFactory[B, That, This]): That = { + val b = bf(thisCollection) + val (prefix, rest) = this.splitAt(from) + b ++= prefix + b ++= patch + b ++= rest drop replaced + b.result + } + /** Returns a new sequence of given length containing the elements of this sequence followed by zero * or more occurrences of given elements. */ - def padTo[B >: A](len: Int, elem: B): CC[B] = { + def padTo[B >: A, That](len: Int, elem: B)(implicit bf: BuilderFactory[B, That, This]): That = { + val b = bf(thisCollection) var diff = len - length - val b = newBuilder[B] //!!! drop [B] and get surprising results! - b ++= thisCC + b ++= thisCollection while (diff > 0) { b += elem diff -=1 @@ -322,33 +455,32 @@ self /*: CC[A]*/ => * * @return the sequence itself */ - override def toSequence: Sequence[A] = thisCC - - /** Force toString from Iterable, not from Function */ - override def toString = super[OrderedIterableTemplate].toString + override def toSequence: Sequence[A] = thisCollection def indices: Range = 0 until length - /** Creates a view of this iterable @see OrderedIterable.View - */ - override def view: SequenceView[CC, A] = new SequenceView[CC, A] { // !!! Martin: We should maybe infer the type parameters here? - val origin: Sequence[_] = thisCC - val elements: Iterator[A] = self.elements - val length: Int = self.length - def apply(idx: Int): A = self.apply(idx) + override def view = new SequenceView[A, This] { + protected lazy val underlying = self.thisCollection + override def elements = self.elements + override def length = self.length + override def apply(idx: Int) = self.apply(idx) } - /** A sub-sequence 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 sequence, whereas `slice` produces a new sequence. - * - * @note view(from, to) is equivalent to view.slice(from, to) + override def view(from: Int, until: Int) = view.slice(from, until) + + override def equals(that: Any): Boolean = that match { + case that1: Sequence[a] => + val these = this.elements + val those = that1.elements + while (these.hasNext && those.hasNext && these.next() == those.next()) {} + !these.hasNext && !those.hasNext + case _ => + false + } + + /** Need to override string, so that it's not the Function1's string that gets mixed in. */ - override def view(from: Int, until: Int): SequenceView[CC, A] = view.slice(from, until) + override def toString = super[IterableTemplate].toString /** Returns index of the last element satisying a predicate, or -1. * @deprecated use `lastIndexWhere` instead @@ -380,4 +512,12 @@ self /*: CC[A]*/ => */ @deprecated def containsSlice[B](that: Sequence[B]): Boolean = indexOf(that) != -1 + /** + * returns a projection that can be used to call non-strict <code>filter</code>, + * <code>map</code>, and <code>flatMap</code> methods that build projections + * of the collection. + * @deprecated use view instead + */ + @deprecated override def projection = view } + diff --git a/src/library/scala/collection/generic/SequenceView.scala b/src/library/scala/collection/generic/SequenceView.scala new file mode 100755 index 0000000000..56b15ac7dc --- /dev/null +++ b/src/library/scala/collection/generic/SequenceView.scala @@ -0,0 +1,28 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ + + +package scala.collection.generic + +import Sequence.fill +import TraversibleView.NoBuilder + +/** A non-strict projection of an iterable. + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ +trait SequenceView[+A, +Coll <: Sequence[_]] extends SequenceViewTemplate[A, Coll, SequenceView[A, Coll]] + +object SequenceView { + type Coll = TraversibleView[_, _] + implicit def builderFactory[A]: BuilderFactory[A, SequenceView[A, Sequence[_]], Coll] = new BuilderFactory[A, SequenceView[A, Sequence[_]], Coll] { def apply(from: Coll) = new NoBuilder } +} + diff --git a/src/library/scala/collection/generic/SequenceViewTemplate.scala b/src/library/scala/collection/generic/SequenceViewTemplate.scala new file mode 100755 index 0000000000..39283763ea --- /dev/null +++ b/src/library/scala/collection/generic/SequenceViewTemplate.scala @@ -0,0 +1,175 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ + + +package scala.collection.generic + +import Sequence.fill +import TraversibleView.NoBuilder + +/** A non-strict projection of an iterable. + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ +trait SequenceViewTemplate[+A, + +Coll <: Sequence[_], + +This <: SequenceView[A, Coll] with SequenceViewTemplate[A, Coll, This]] + extends Sequence[A] with SequenceTemplate[A, This] with IterableView[A, Coll] with IterableViewTemplate[A, Coll, This] +{ self => + + trait Transformed[+B] extends SequenceView[B, Coll] with super.Transformed[B] { + override def length: Int + override def apply(idx: Int): B + } + + trait Sliced extends Transformed[A] with super.Sliced { + override def length = ((until min self.length) - from) max 0 + override def apply(idx: Int): A = + if (idx + from < until) self.apply(idx + from) + else throw new IndexOutOfBoundsException(idx.toString) + } + + trait Mapped[B] extends Transformed[B] with super.Mapped[B] { + override def length = self.length + override def apply(idx: Int): B = mapping(self apply idx) + } + + trait FlatMapped[B] extends Transformed[B] with super.FlatMapped[B] { + protected[this] lazy val index = { + val index = new Array[Int](self.length + 1) + index(0) = 0 + for (i <- 0 until self.length) + index(i + 1) = index(i) + mapping(self(i)).size + index + } + protected[this] def findRow(idx: Int, lo: Int, hi: Int): Int = { + val mid = (lo + hi) / 2 + if (idx < index(mid)) findRow(idx, lo, mid - 1) + else if (idx >= index(mid + 1)) findRow(idx, mid + 1, hi) + else mid + } + override def length = index(self.length) + override def apply(idx: Int) = { + val row = findRow(idx, 0, self.length - 1) + mapping(self(row)).toSequence(idx - index(row)) + } + } + + trait Appended[B >: A] extends Transformed[B] with super.Appended[B] { + lazy val restSeq = rest.toSequence + override def length = self.length + restSeq.length + override def apply(idx: Int) = + if (idx < self.length) self(idx) else restSeq(idx - self.length) + } + + trait Filtered extends Transformed[A] with super.Filtered { + protected[this] lazy val index = { + var len = 0 + val arr = new Array[Int](self.length) + for (i <- 0 until self.length) + if (pred(self(i))) { + arr(len) = i + len += 1 + } + arr take len + } + override def length = index.length + override def apply(idx: Int) = self(index(idx)) + } + + trait TakenWhile extends Transformed[A] with super.TakenWhile { + protected[this] lazy val len = self prefixLength pred + override def length = len + override def apply(idx: Int) = + if (idx < len) self(idx) + else throw new IndexOutOfBoundsException(idx.toString) + } + + trait DroppedWhile extends Transformed[A] with super.DroppedWhile { + protected[this] lazy val start = self prefixLength pred + override def length = self.length - start + override def apply(idx: Int) = + if (idx >= 0) self(idx + start) + else throw new IndexOutOfBoundsException(idx.toString) + } + + trait Reversed extends Transformed[A] { + override def elements: Iterator[A] = self.reversedElements + override def length: Int = self.length + override def apply(idx: Int): A = self.apply(length - 1 - idx) + override def stringPrefix = super.stringPrefix+"R" + } + + trait Patched[B >: A] extends Transformed[B] { + protected[this] val from: Int + protected[this] val patch: Sequence[B] + protected[this] val replaced: Int + private val plen = patch.length + override def elements: Iterator[B] = self.elements patch (from, patch.elements, replaced) + override def length: Int = self.length + plen - replaced + override def apply(idx: Int): B = + if (idx < from) self.apply(idx) + else if (idx < from + plen) patch.apply(idx - from) + else self.apply(idx - plen + replaced) + override def stringPrefix = super.stringPrefix+"P" + } + + trait Zipped[B] extends Transformed[(A, B)] { + protected[this] val other: Sequence[B] + override def elements: Iterator[(A, B)] = self.elements zip other.elements + override def length = self.length min other.length + override def apply(idx: Int): (A, B) = (self.apply(idx), other.apply(idx)) + override def stringPrefix = super.stringPrefix+"Z" + } + + /** Boilerplate method, to override in each subclass + * This method could be eliminated if Scala had virtual classes + */ + protected override def newAppended[B >: A](that: Traversible[B]): Transformed[B] = new Appended[B] { val rest = that } + protected override def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f } + protected override def newFlatMapped[B](f: A => Traversible[B]): Transformed[B] = new FlatMapped[B] { val mapping = f } + protected override def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p } + protected override def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until } + protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p } + protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p } + protected def newReversed: Transformed[A] = new Reversed { } + protected def newPatched[B >: A](_from: Int, _patch: Sequence[B], _replaced: Int): Transformed[B] = new Patched[B] { + val from = _from; val patch = _patch; val replaced = _replaced + } + protected def newZipped[B](that: Sequence[B]): Transformed[(A, B)] = new Zipped[B] { + val other = that + } + + override def reverse: This = newReversed.asInstanceOf[This] + + override def patch[B >: A, That](from: Int, patch: Sequence[B], replaced: Int)(implicit bf: BuilderFactory[B, That, This]): That = { + val b = bf(thisCollection) + if (b.isInstanceOf[NoBuilder[_]]) newPatched(from, patch, replaced).asInstanceOf[That] + else super.patch[B, That](from, patch, replaced)(bf) + } + + override def padTo[B >: A, That](len: Int, elem: B)(implicit bf: BuilderFactory[B, That, This]): That = + patch(length, fill(len - length)(elem), 0) + + override def zip[A1 >: A, B, That](that: Sequence[B])(implicit bf: BuilderFactory[(A1, B), That, This]): That = { + val b = bf(thisCollection) + if (b.isInstanceOf[NoBuilder[_]]) newZipped(that).asInstanceOf[That] + else super.zip[A1, B, That](that)(bf) + } + + override def zipWithIndex[A1 >: A, That](implicit bf: BuilderFactory[(A1, Int), That, This]): That = + zip[A1, Int, That](Sequence.range(0, length))(bf) + + override def zipAll[B, A1 >: A, That](that: Sequence[B], thisElem: A1, thatElem: B)(implicit bf: BuilderFactory[(A1, B), That, This]): That = + self.padTo(that.length, thisElem).zip(that.padTo(this.length, thatElem))(bf.asInstanceOf[BuilderFactory[(A1, B), That, Any]]) +} + + diff --git a/src/library/scalax/collection/generic/AddableBuilder.scala b/src/library/scala/collection/generic/SetBuilder.scala index b1f3e4e522..ab8f1bee73 100644 --- a/src/library/scalax/collection/generic/AddableBuilder.scala +++ b/src/library/scala/collection/generic/SetBuilder.scala @@ -8,15 +8,19 @@ // $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ -package scalax.collection.generic +package scala.collection.generic -import collection.mutable.ListBuffer -import collection.immutable.{List, Nil, ::} +// import collection.immutable.{List, Nil, ::} -class AddableBuilder[CC[B] <: Iterable[B] with Addable[CC[B], B], A](empty: CC[A]) extends Builder[CC, A] { - protected var elems: CC[A] = empty +/** The canonical builder for collections that are addable, i.e. that support an efficient + method + * which adds an element to the collection. + * Collections are built from their empty element using this + method. + * @param empty The empty element of the collection. + */ +class SetBuilder[A, Coll <: Addable[A, Coll] with Iterable[A] with IterableTemplate[A, Coll]](empty: Coll) +extends Builder[A, Coll, Any] { + protected var elems: Coll = empty def +=(x: A) { elems = elems + x } - def elements: Iterator[A] = elems.elements def clear() { elems = empty } - def result: CC[A] = elems + def result: Coll = elems } diff --git a/src/library/scala/collection/generic/SetFactory.scala b/src/library/scala/collection/generic/SetFactory.scala new file mode 100755 index 0000000000..a2caa99432 --- /dev/null +++ b/src/library/scala/collection/generic/SetFactory.scala @@ -0,0 +1,16 @@ +package scala.collection.generic + +/** A template for companion objects of Map and subclasses thereof. + */ +abstract class SetFactory[CC[A] <: Set[A] with SetTemplate[A, CC[A]]] { + + def newBuilder[A]: Builder[A, CC[A], Any] = new AddingBuilder[A, CC[A]](empty[A]) + + def empty[A]: CC[A] + + def apply[A](elems: A*): CC[A] = { + var s = empty[A] + for (elem <- elems) s = s + elem + s + } +} diff --git a/src/library/scalax/collection/generic/SetTemplate.scala b/src/library/scala/collection/generic/SetTemplate.scala index bd94f10fc0..865d4a333b 100755 --- a/src/library/scalax/collection/generic/SetTemplate.scala +++ b/src/library/scala/collection/generic/SetTemplate.scala @@ -6,46 +6,31 @@ ** |/ ** \* */ -// $Id: Set.scala 16893 2009-01-13 13:09:22Z cunei $ - - -package scalax.collection.generic - - -/** <p> - * A set is a collection that includes at most one of any object. - * </p> - * <p> - * This trait provides a limited interface, only allowing reading of elements. - * There are two extensions of this trait, in packages - * <code><a href="mutable$content.html" target="contentFrame"> - * scala.collection.mutable</a></code> - * and <code><a href="immutable$content.html" target="contentFrame"> - * scala.collection.immutable</a></code>, which provide functionality for - * adding and removing objects from the set. The trait in the first package is - * for sets that are modified destructively, whereas the trait in - * the second package is for immutable sets which create a new set - * when something is added or removed to them. +// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ + +package scala.collection.generic + +/** A generic template for sets of type A. + * To implement a concrete set, you need to provide implementations of the following methods: + * (where This is the type of the set in question): + * + * def contains(key: A): Boolean + * def elements: Iterator[A] + * def +(elem: A): This + * def -(elem: A): This * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.8 + * If you wish that methods like, take, drop, filter return the same kind of set, you should also + * override: + * + * def empty: This + * + * It is also good idea to override methods foreach and size for efficiency. */ -trait SetTemplate[+CC[B] <: SetTemplate[CC, B] with Set[B], A] - extends (A => Boolean) - with SizedIterable[A] - with IterableTemplate[CC, A] - with Addable[CC[A], A] - with Subtractable[CC[A], A] { - - /** Returns the number of elements in this set. - * - * @return number of set elements. - */ - def size: Int +trait SetTemplate[A, +This <: SetTemplate[A, This] with Set[A]] extends IterableTemplate[A, This] with Addable[A, This] with Subtractable[A, This] { self => + + def empty: This - /** Creates a new set of this kind with given elements */ - def newBuilder[B]: Builder[CC, B] + override protected[this] def newBuilder: Builder[A, This, Any] = new AddingBuilder[A, This](empty) /** Checks if this set contains element <code>elem</code>. * @@ -55,15 +40,15 @@ trait SetTemplate[+CC[B] <: SetTemplate[CC, B] with Set[B], A] */ def contains(elem: A): Boolean - /** Create a new set with an additional element. + /** Creates a new set with an additional element, unless the element is already present. + * @param elem the element to be added */ - def + (elem: A): CC[A] + def + (elem: A): This - /** Remove a single element from a set. + /** Removes a single element from a set, unless the element is not present. * @param elem the element to be removed - * @return a new set with the element removed. */ - def - (elem: A): CC[A] + def - (elem: A): This /** Checks if this set is empty. * @@ -86,7 +71,16 @@ trait SetTemplate[+CC[B] <: SetTemplate[CC, B] with Set[B], A] * * @param that the set to intersect with. */ - def intersect(that: Set[A]): CC[A] = filter(that.contains) + def intersect(that: Set[A]): This = filter(that.contains) + + /** This method is an alias for <code>intersect</code>. + * It computes an intersection with set <code>that</code>. + * It removes all the elements that are not present in <code>that</code>. + * + * @param that the set to intersect with + * @deprecated use & instead + */ + @deprecated def ** (that: Set[A]): This = intersect(that) /** This method is an alias for <code>intersect</code>. * It computes an intersection with set <code>that</code>. @@ -94,7 +88,20 @@ trait SetTemplate[+CC[B] <: SetTemplate[CC, B] with Set[B], A] * * @param that the set to intersect with */ - def ** (that: collection.Set[A]): CC[A] = intersect(that) + def & (that: collection.Set[A]): This = intersect(that) + + /** Computes the union of this set and the given set <code>that</code>. + * + * @param that the sequence of elements to add to the sequence. + * @return a set containing the elements of this + * set and those of the given set <code>that</code>. + */ + def union(that: Set[A]): This = (thisCollection /: that) (_ + _) + + /** This method is an alias for <code>union</code>. + * It computes the union of this set and the given set <code>that</code>. + */ + def | (that: Set[A]): This = union(that) /** Checks if this set is a subset of set <code>that</code>. * @@ -105,9 +112,6 @@ trait SetTemplate[+CC[B] <: SetTemplate[CC, B] with Set[B], A] */ def subsetOf(that: Set[A]): Boolean = forall(that.contains) -/* What a mess! We need to remove these methods, but can't without breaking - * existing code. What to do? - /** Compares this set with another object and returns true, iff the * other object is also a set which contains the same elements as * this set. @@ -116,28 +120,20 @@ trait SetTemplate[+CC[B] <: SetTemplate[CC, B] with Set[B], A] * @note not necessarily run-time type safe. * @return <code>true</code> iff this set and the other set * contain the same elements. - * @deprecated equals is not stable for mutable sets. - * If you wish object identity, use eq or cast this set of AnyRef and then use - * equals. If you wish element comparisons, use `sameElements` instead. */ - @deprecated override def equals(that: Any): Boolean = that match { + override def equals(that: Any): Boolean = that match { case other: Set[_] => - this.size == other.size && subsetOf(other.asInstanceOf[Set[A]]) + if (this.size == other.size) + try { // can we find a safer way to do this? + subsetOf(other.asInstanceOf[Set[A]]) + } catch { + case ex: ClassCastException => false + } + else false case _ => false } - /* @deprecated Since the previous hashCode is not stable for mutable sets, - * the implementation of this method has been changed to - * standard address-based hashCode from java.lang.Object. - * If you relied on the old behavior, y - * IT has been - * if you intend to have object identity hashCode and wish the deprecated warning - * to go away, cast this set to AnyRef before calling hashCode. - */ - @deprecated override def hashCode() = - (0 /: this)((hash, e) => hash + e.hashCode()) -*/ /** Defines the prefix of this object's <code>toString</code> representation. */ override def stringPrefix: String = "Set" @@ -146,3 +142,6 @@ trait SetTemplate[+CC[B] <: SetTemplate[CC, B] with Set[B], A] */ override def toString = super[IterableTemplate].toString } + + + diff --git a/src/library/scalax/collection/generic/Shrinkable.scala b/src/library/scala/collection/generic/Shrinkable.scala index e6d3b085f3..1c4987b90b 100755 --- a/src/library/scalax/collection/generic/Shrinkable.scala +++ b/src/library/scala/collection/generic/Shrinkable.scala @@ -8,7 +8,7 @@ // $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ -package scalax.collection.generic +package scala.collection.generic /** This class represents collections that can be reduced using a -= operator. * @@ -16,7 +16,7 @@ package scalax.collection.generic * @owner Martin Odersky * @version 2.8 */ -trait Shrinkable[A] { +trait Shrinkable[-A] { /** Removes a single element from this collection. * @@ -33,20 +33,20 @@ trait Shrinkable[A] { def -=(elem1: A, elem2: A, elems: A*) { this -= elem1 this -= elem2 - this --= elems.asInstanceOf[Iterable[A]] // !@! + this --= Iterable.fromOld(elems) } /** Removes a number of elements provided by an iterator from this collection. * * @param iter the iterator. */ - def --=(iter: collection.Iterator[A]) { iter foreach -= } + def --=(iter: Iterator[A]) { iter foreach -= } /** Removes a number of elements provided by an iterable object from this collection. * * @param iter the iterable object. */ - def --=(iter: collection.Iterable[A]) { iter foreach -= } + def --=(iter: Traversible[A]) { iter foreach -= } } diff --git a/src/library/scala/collection/Sorted.scala b/src/library/scala/collection/generic/Sorted.scala index fcd2a64463..007629811f 100644 --- a/src/library/scala/collection/Sorted.scala +++ b/src/library/scala/collection/generic/Sorted.scala @@ -6,48 +6,34 @@ ** |/ ** \* */ -// $Id$ +// $Id: Sorted.scala 17537 2009-04-20 18:37:37Z odersky $ -package scala.collection +package scala.collection.generic /** Any collection (including maps) whose keys (or elements) are ordered. * * @author Sean McDirmid */ -trait Sorted[K,+A] extends Ranged[K,A] { +trait Sorted[K, +This <: Sorted[K, This]] extends Ranged[K, This] { + + /** The current collection */ + protected def thisCollection: This /** return as a projection the set of keys in this collection */ def keySet: SortedSet[K] - /** Creates a ranged projection of this collection. Any mutations in the - * ranged projection will update this collection and vice versa. Keys - * are garuanteed to be consistent between the collection and its projection. - * - * @param from The lower-bound (inclusive) of the ranged projection. - * <code>None</code> if there is no lower bound. - * @param until The upper-bound (exclusive) of the ranged projection. - * <code>None</code> if there is no upper bound. - */ - override def rangeImpl(from: Option[K], until: Option[K]): Sorted[K,A] - - override def from(from: K) = rangeImpl(Some(from), None) - - override def until(until: K) = rangeImpl(None, Some(until)) - - override def range(from: K, until: K) = rangeImpl(Some(from),Some(until)) - /** Create a range projection of this collection with no lower-bound. * @param to The upper-bound (inclusive) of the ranged projection. */ - def to(to: K): Sorted[K,A] = { + def to(to: K): This = { // tough! val i = keySet.from(to).elements; - if (!i.hasNext) return this; + if (!i.hasNext) return thisCollection val next = i.next; if (next == to) { - if (!i.hasNext) return this; - else return until(i.next); - } else return until(next); + if (!i.hasNext) return thisCollection + else return until(i.next) + } else return until(next) } protected def hasAll(j: Iterator[K]): Boolean = { diff --git a/src/library/scala/collection/generic/SortedMapTemplate.scala b/src/library/scala/collection/generic/SortedMapTemplate.scala new file mode 100755 index 0000000000..8c7e4eb54f --- /dev/null +++ b/src/library/scala/collection/generic/SortedMapTemplate.scala @@ -0,0 +1,69 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: SortedMap.scala 16893 2009-01-13 13:09:22Z cunei $ +package scala.collection.generic + +/** A template for maps whose keys are sorted. + * To create a concrete sorted map, you need to implement the rangeImpl method, + * in addition to those of `MapTemplate`. + * + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ +trait SortedMapTemplate[A, +B, +This <: SortedMapTemplate[A, B, This] with SortedMap[A, B]] extends Sorted[A, This] with MapTemplate[A, B, This] { +self => + + def firstKey : A = head._1 + def lastKey : A = last._1 + + // XXX: implement default version + def rangeImpl(from : Option[A], until : Option[A]) : This + + protected class DefaultKeySet extends super.DefaultKeySet with SortedSet[A] { + def compare(k0: A, k1: A) = self.thisCollection.compare(k0, k1) + /** We can't give an implementation of +/- here because we do not have a generic sorted set implementation + */ + override def + (elem: A): SortedSet[A] = throw new UnsupportedOperationException("keySet.+") + override def - (elem: A): SortedSet[A] = throw new UnsupportedOperationException("keySet.-") + override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = { + val map = self.rangeImpl(from, until) + new map.DefaultKeySet + } + } + + override def keySet : SortedSet[A] = new DefaultKeySet + + /** Add a key/value pair to this map. + * @param key the key + * @param value the value + * @return A new map with the new binding added to this map + */ + def add [B1 >: B](key: A, value: B1): SortedMap[A, B1] + + /** Add a key/value pair to this map. + * @param kv the key/value pair + * @return A new map with the new binding added to this map + */ + override def + [B1 >: B] (kv: (A, B1)): SortedMap[A, B1] = add(kv._1, kv._2) + + /** Adds two or more elements to this collection and returns + * either the collection itself (if it is mutable), or a new collection + * with the added elements. + * + * @param elem1 the first element to add. + * @param elem2 the second element to add. + * @param elems the remaining elements to add. + */ + override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): SortedMap[A, B1] = { + var m = this + elem1 + elem2; + for (e <- elems) m = m + e + m + } +} diff --git a/src/library/scala/collection/generic/SortedSetTemplate.scala b/src/library/scala/collection/generic/SortedSetTemplate.scala new file mode 100755 index 0000000000..4d02e93ba0 --- /dev/null +++ b/src/library/scala/collection/generic/SortedSetTemplate.scala @@ -0,0 +1,38 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: SortedSet.scala 16893 2009-01-13 13:09:22Z cunei $ +// !!! todo: integrate in new collections library + +package scala.collection.generic + +/** A template for sets which are sorted. + * + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ +trait SortedSetTemplate[A, +This <: SortedSet[A] with SortedSetTemplate[A, This]] extends Sorted[A, This] with SetTemplate[A, This] { +self => + + override def keySet = thisCollection + + override def firstKey: A = head + override def lastKey: A = last + + def rangeImpl(from: Option[A], until: Option[A]): This + + override def from(from: A): This = rangeImpl(Some(from), None) + override def until(until: A): This = rangeImpl(None, Some(until)) + override def range(from: A, until: A): This = rangeImpl(Some(from), Some(until)) + + override def subsetOf(that: Set[A]): Boolean = that match { + case that: SortedSet[_] => that.hasAll(elements) + case that => super.subsetOf(that) + } +} diff --git a/src/library/scalax/collection/generic/Subtractable.scala b/src/library/scala/collection/generic/Subtractable.scala index 93fe2f8190..498b2faf5c 100755 --- a/src/library/scalax/collection/generic/Subtractable.scala +++ b/src/library/scala/collection/generic/Subtractable.scala @@ -8,7 +8,7 @@ // $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ -package scalax.collection.generic +package scala.collection.generic /** This class represents collections that can be reduced using a -= operator. * @@ -16,9 +16,9 @@ package scalax.collection.generic * @owner Martin Odersky * @version 2.8 */ -trait Subtractable[+C <: Subtractable[C, A], A] { +trait Subtractable[A, +This <: Subtractable[A, This]] { self => - protected def thisCC: C + protected def thisCollection: This /** Removes a single element from this collection and returns * either the collection itself (if it is mutable), or a new collection @@ -26,7 +26,7 @@ trait Subtractable[+C <: Subtractable[C, A], A] { * * @param elem the element to remove. */ - def -(elem: A): C + def -(elem: A): This /** Removes two or more elements from this collection and returns * either the collection itself (if it is mutable), or a new collection @@ -36,8 +36,8 @@ trait Subtractable[+C <: Subtractable[C, A], A] { * @param elem2 the second element to remove. * @param elems the remaining elements to remove. */ - def -(elem1: A, elem2: A, elems: A*): C = - thisCC - elem1 - elem2 -- elems.asInstanceOf[Iterable[A]] // !@! + def -(elem1: A, elem2: A, elems: A*): This = + this - elem1 - elem2 -- Iterable.fromOld(elems) /** Removes a number of elements provided by an iterable object * via its <code>elements</code> method and returns @@ -46,7 +46,7 @@ trait Subtractable[+C <: Subtractable[C, A], A] { * * @param iter the iterable object. */ - def --(iter: Iterable[A]): C = (thisCC /: iter) (_ - _) + def --(iter: Traversible[A]): This = (thisCollection /: iter) (_ - _) /** Removes a number of elements provided by an iterator * via its <code>elements</code> method and returns @@ -55,7 +55,7 @@ trait Subtractable[+C <: Subtractable[C, A], A] { * * @param iter the iterator */ - def --(iter: Iterator[A]): C = (thisCC /: iter) (_ - _) + def --(iter: Iterator[A]): This = (thisCollection /: iter) (_ - _) } diff --git a/src/library/scala/collection/generic/TraversibleFactory.scala b/src/library/scala/collection/generic/TraversibleFactory.scala new file mode 100755 index 0000000000..7d054c1b81 --- /dev/null +++ b/src/library/scala/collection/generic/TraversibleFactory.scala @@ -0,0 +1,183 @@ + package scala.collection.generic + +/** A template for companion objects of Traversible and subclasses thereof. + */ +abstract class TraversibleFactory[CC[A] <: Traversible[A]] { + + /** The builder for this kind of collection. + */ + def newBuilder[A]: Builder[A, CC[A], Any] + + /** The empty iterable of type CC */ + def empty[A]: CC[A] = newBuilder[A].result + + /** Creates an iterable of type CC with specified elements */ + def apply[A](args: A*): CC[A] = { + val b = newBuilder[A] + b ++= Iterable.fromOld(args) + b.result + } + + /** Concatenate all the argument collections into a single collection. + * + * @param xss the collections that are to be concatenated + * @return the concatenation of all the collections + */ + def concat[A](xss: Traversible[A]*): CC[A] = { + val b = newBuilder[A] + for (xs <- xss) b ++= xs + b.result + } + + /** An iterable that contains the results of some element computation a number of times. + * @param n the number of elements returned + * @param elem the element computation + */ + def fill[A](n: Int)(elem: => A): CC[A] = { + val b = newBuilder[A] + var i = 0 + while (i < n) { + b += elem + i += 1 + } + b.result + } + + /** A two-dimensional iterable that contains the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param elem the element computation + */ + def fill[A](n1: Int, n2: Int)(elem: => A): CC[CC[A]] = + tabulate(n1)(_ => fill(n2)(elem)) + + /** A three-dimensional iterable that contains the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param elem the element computation + */ + def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]]] = + tabulate(n1)(_ => fill(n2, n3)(elem)) + + /** A four-dimensional iterable that contains the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param elem the element computation + */ + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]]] = + tabulate(n1)(_ => fill(n2, n3, n4)(elem)) + + /** A five-dimensional iterable that contains the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param n5 the number of elements in the 5th dimension + * @param elem the element computation + */ + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]]] = + tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) + + /** An iterable containing values of a given function over a range of integer values starting from 0. + * @param n The number of elements in the iterable + * @param f The function computing element values + * @return An iterable consisting of elements `f(0), ..., f(n -1)` + */ + def tabulate[A](n: Int)(f: Int => A): CC[A] = { + val b = newBuilder[A] + var i = 0 + while (i < n) { + b += f(i) + i += 1 + } + b.result + } + + /** A two-dimensional iterable containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param f The function computing element values + */ + def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] = + tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) + + /** A three-dimensional iterable containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param f The function computing element values + */ + def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] = + tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) + + /** A four-dimensional iterable containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param f The function computing element values + */ + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]]] = + tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) + + /** A five-dimensional iterable containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param n5 the number of elements in the 5th dimension + * @param f The function computing element values + */ + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]]] = + tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) + + /** An iterable containing a sequence of increasing integers in a range. + * + * @param from the start value of the iterable + * @param end the end value of the iterable (the first value NOT returned) + * @return the iterable with values in range `start, start + 1, ..., end - 1` + * up to, but exclusding, `end`. + */ + def range[A](start: Int, end: Int): CC[Int] = range(start, end, 1) + + /** An iterable containing equally spaced values in some integer interval. + + * @param start the start value of the iterable + * @param end the end value of the iterable (the first value NOT returned) + * @param step the increment value of the iterable (must be positive or negative) + * @return the iterable with values in `start, start + step, ...` up to, but excluding `end` + */ + def range(start: Int, end: Int, step: Int): CC[Int] = { + if (step == 0) throw new IllegalArgumentException("zero step") + val b = newBuilder[Int] + var i = start + while (if (step < 0) end < i else i < end) { + b += i + i += step + } + b.result + } + + /** An iterable containing repeated applications of a function to a start value. + * + * @param start the start value of the iterable + * @param len the number of elements returned by the iterable + * @param f the function that's repeatedly applied + * @return the iterable returning `len` values in the sequence `start, f(start), f(f(start)), ...` + */ + def iterate(start: Int, len: Int)(f: Int => Int): CC[Int] = { + val b = newBuilder[Int] + var acc = start + var i = 0 + while (i < len) { + b += acc + acc = f(acc) + i += 1 + } + b.result + } +} + diff --git a/src/library/scalax/collection/generic/covartest/IterableForwarder.scala b/src/library/scala/collection/generic/TraversibleForwarder.scala index 58290cfc68..855289d36c 100755 --- a/src/library/scalax/collection/generic/covartest/IterableForwarder.scala +++ b/src/library/scala/collection/generic/TraversibleForwarder.scala @@ -9,32 +9,31 @@ // $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ -package scalax.collection.generic.covartest +package scala.collection.generic -import collection.mutable.Buffer -import collection.immutable.{List, Stream} +import mutable.Buffer +// import immutable.{List, Nil, ::, Stream} -/** This trait implements a forwarder for iterable objects. It forwards +/** This trait implements a forwarder for traversible objects. It forwards * all calls to a different iterable object, except for * * - toString, hashCode, equals, stringPrefix * - newBuilder, view - * - all calls creating a new iterable objetc of the same kind + * - all calls creating a new iterable object of the same kind * - * The above methods are forwarded by subclass IterableProxy + * The above methods are forwarded by subclass TraversibleProxy * * @author Martin Odersky * @version 2.8 */ -trait IterableForwarder[+A] extends Iterable[A] { +trait TraversibleForwarder[+A] extends Traversible[A] { /** The iterable object to which calls are forwarded */ - protected def underlying: Iterable[A] + protected def underlying: Traversible[A] // Iterable delegates // Iterable methods could be printed by cat IterableTemplate.scala | sed -n '/trait Iterable/,$ p' | egrep '^ (override )?def' - override def elements = underlying.elements override def isEmpty = underlying.isEmpty override def hasDefiniteSize = underlying.hasDefiniteSize override def foreach(f: A => Unit) = underlying.foreach(f) @@ -46,6 +45,8 @@ trait IterableForwarder[+A] extends Iterable[A] { override def foldRight[B](z: B)(op: (A, B) => B): B = underlying.foldRight(z)(op) override def reduceLeft[B >: A](op: (B, A) => B): B = underlying.reduceLeft(op) override def reduceRight[B >: A](op: (A, B) => B): B = underlying.reduceRight(op) + override def reduceLeftOpt[B >: A](op: (B, A) => B): Option[B] = underlying.reduceLeftOpt(op) + override def reduceRightOpt[B >: A](op: (A, B) => B): Option[B] = underlying.reduceRightOpt(op) override def copyToBuffer[B >: A](dest: Buffer[B]) = underlying.copyToBuffer(dest) override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) = underlying.copyToArray(xs, start, len) override def toArray[B >: A]: Array[B] = underlying.toArray @@ -56,4 +57,6 @@ trait IterableForwarder[+A] extends Iterable[A] { override def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = underlying.addString(b, start, sep, end) override def head: A = underlying.head + override def last: A = underlying.last + override def lastOption: Option[A] = underlying.lastOption } diff --git a/src/library/scala/collection/generic/TraversibleProxyTemplate.scala b/src/library/scala/collection/generic/TraversibleProxyTemplate.scala new file mode 100755 index 0000000000..0c17aa4121 --- /dev/null +++ b/src/library/scala/collection/generic/TraversibleProxyTemplate.scala @@ -0,0 +1,84 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ + + +package scala.collection.generic + +import collection.mutable.Buffer + +// Methods could be printed by cat TraversibeTemplate.scala | egrep '^ (override )?def' + + +/** This trait implements a proxy for traversible objects. It forwards + * all calls to a different traversible object + * + * @author Martin Odersky + * @version 2.8 + */ +trait TraversibleProxyTemplate[+A, +This <: TraversibleTemplate[A, This] with Traversible[A]] extends TraversibleTemplate[A, This] with Proxy { + def self: This + + override def isEmpty: Boolean = self.isEmpty + override def size: Int = self.size + override def hasDefiniteSize = self.hasDefiniteSize + override def ++[B >: A, That](that: Traversible[B])(implicit bf: BuilderFactory[B, That, This]): That = self.++(that)(bf) + override def ++[B >: A, That](that: Iterator[B])(implicit bf: BuilderFactory[B, That, This]): That = self.++(that)(bf) + override def map[B, That](f: A => B)(implicit bf: BuilderFactory[B, That, This]): That = self.map(f)(bf) + override def flatMap[B, That](f: A => Traversible[B])(implicit bf: BuilderFactory[B, That, This]): That = self.flatMap(f)(bf) + override def filter(p: A => Boolean): This = self.filter(p) + override def remove(p: A => Boolean): This = self.remove(p) + override def partition(p: A => Boolean): (This, This) = self.partition(p) + override def groupBy[K](f: A => K): Map[K, This] = self.groupBy(f) + override def foreach(f: A => Unit): Unit = self.foreach(f) + override def forall(p: A => Boolean): Boolean = self.forall(p) + override def exists(p: A => Boolean): Boolean = self.exists(p) + override def count(p: A => Boolean): Int = self.count(p) + override def find(p: A => Boolean): Option[A] = self.find(p) + override def foldLeft[B](z: B)(op: (B, A) => B): B = self.foldLeft(z)(op) + override def /: [B](z: B)(op: (B, A) => B): B = self./:(z)(op) + override def foldRight[B](z: B)(op: (A, B) => B): B = self.foldRight(z)(op) + override def :\ [B](z: B)(op: (A, B) => B): B = self.:\(z)(op) + override def reduceLeft[B >: A](op: (B, A) => B): B = self.reduceLeft(op) + override def reduceLeftOpt[B >: A](op: (B, A) => B): Option[B] = self.reduceLeftOpt(op) + override def reduceRight[B >: A](op: (A, B) => B): B = self.reduceRight(op) + override def reduceRightOpt[B >: A](op: (A, B) => B): Option[B] = self.reduceRightOpt(op) + override def head: A = self.head + override def headOption: Option[A] = self.headOption + override def tail: This = self.tail + override def last: A = self.last + override def lastOption: Option[A] = self.lastOption + override def init: This = self.init + override def take(n: Int): This = self.take(n) + override def drop(n: Int): This = self.drop(n) + override def slice(from: Int, until: Int): This = self.slice(from, until) + override def takeWhile(p: A => Boolean): This = self.takeWhile(p) + override def dropWhile(p: A => Boolean): This = self.dropWhile(p) + override def span(p: A => Boolean): (This, This) = self.span(p) + override def splitAt(n: Int): (This, This) = self.splitAt(n) + override def copyToBuffer[B >: A](dest: Buffer[B]) = self.copyToBuffer(dest) + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) = self.copyToArray(xs, start, len) + override def copyToArray[B >: A](xs: Array[B], start: Int) = self.copyToArray(xs, start) + override def toArray[B >: A]: Array[B] = self.toArray + override def toList: List[A] = self.toList + override def toIterable: Iterable[A] = self.toIterable + override def toSequence: Sequence[A] = self.toSequence + override def toStream: Stream[A] = self.toStream +// override def sortWith(lt : (A,A) => Boolean): This = self.sortWith(lt) + override def mkString(start: String, sep: String, end: String): String = self.mkString(start, sep, end) + override def mkString(sep: String): String = self.mkString(sep) + override def mkString: String = self.mkString + override def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = self.addString(b, start, sep, end) + override def addString(b: StringBuilder, sep: String): StringBuilder = self.addString(b, sep) + override def addString(b: StringBuilder): StringBuilder = self.addString(b) + override def toString = self.toString + override def stringPrefix : String = self.stringPrefix + override def view = self.view + override def view(from: Int, until: Int): TraversibleView[A, This] = self.view(from, until) +} diff --git a/src/library/scala/collection/generic/TraversibleTemplate.scala b/src/library/scala/collection/generic/TraversibleTemplate.scala new file mode 100755 index 0000000000..2ec74ba874 --- /dev/null +++ b/src/library/scala/collection/generic/TraversibleTemplate.scala @@ -0,0 +1,742 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Traversible.scala 15188 2008-05-24 15:01:02Z stepancheg $ +package scala.collection.generic + +// import immutable.{List, Stream, Nil} //!!! +import mutable.{Buffer, ArrayBuffer, ListBuffer} +import util.control.Breaks._ + +/** A template trait for traversible collections. + * + * Collection classes mixing in this trait provide a method + * <code>foreach</code> which traverses all the + * elements contained in the collection, applying a given procedure to each. + * They also provide a method `newBuilder` + * which creates a builder for collections of the same kind. + * + * @author Martin Odersky + * @version 2.8 + */ +trait TraversibleTemplate[+A, +This <: TraversibleTemplate[A, This] with Traversible[A]] { +self => + + protected def thisCollection: This = this.asInstanceOf[This] + + /** Create a new builder for this traversible type. + */ + protected[this] def newBuilder: Builder[A, This, Any] + + /** Is this collection empty? + */ + def isEmpty: Boolean = { + var result = true + breakable { + for (x <- this) { + result = false + break + } + } + result + } + + /** The number of elements in this collection */ + def size: Int = { + var result = 0 + breakable { + for (x <- this) result += 1 + } + result + } + + /** returns true iff this collection has a finite size. + * Many methods in this trait will not work on collections of + * infinite sizes. + */ + def hasDefiniteSize = true + + /** Creates a new traversible of type `That` which contains all elements of this traversible + * followed by all elements of another traversible + * + * @param that The traversible to append + */ + def ++[B >: A, That](that: Traversible[B])(implicit bf: BuilderFactory[B, That, This]): That = { + val b = bf(thisCollection) + b ++= thisCollection + b ++= that + b.result + } + + /** Create a new traversible of type `That` which contains all elements of this traversible + * followed by all elements of an iterator + * + * @param that The iterator to append + */ + def ++[B >: A, That](that: Iterator[B])(implicit bf: BuilderFactory[B, That, This]): That = { + val b = bf(thisCollection) + b ++= thisCollection + b ++= that + b.result + } + + /** Returns the traversible that results from applying the given function + * <code>f</code> to each element of this traversible and collecing the results + * in an traversible of type `That`. + * + * @param f function to apply to each element. + * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> if this + * traversible is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. + */ + def map[B, That](f: A => B)(implicit bf: BuilderFactory[B, That, This]): That = { + val b = bf(thisCollection) + for (x <- this) b += f(x) + b.result + } + + /** Applies the given function <code>f</code> to each element of + * this traversible, then concatenates the results in an traversible of type CC. + * + * @param f the function to apply on each element. + * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if + * this traversible is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. + */ + def flatMap[B, That](f: A => Traversible[B])(implicit bf: BuilderFactory[B, That, This]): That = { + val b = bf(thisCollection) + for (x <- this) b ++= f(x) + b.result + } + + /** Returns all the elements of this traversible that satisfy the + * predicate <code>p</code>. The order of the elements is preserved. + * @param p the predicate used to filter the traversible. + * @return the elements of this traversible satisfying <code>p</code>. + */ + def filter(p: A => Boolean): This = { + val b = newBuilder + for (x <- this) + if (p(x)) b += x + b.result + } + + /** Removes all elements of the traversible which satisfy the predicate + * <code>p</code>. This is like <code>filter</code> with the + * predicate inversed. + * + * @param p the predicate used to test elements + * @return the traversible without all elements that satisfy <code>p</code> + */ + def remove(p: A => Boolean): This = filter(!p(_)) + + /** Partitions this traversible in two traversibles according to a predicate. + * + * @param p the predicate on which to partition + * @return a pair of traversibles: the traversible that satisfies the predicate + * <code>p</code> and the traversible that does not. + * The relative order of the elements in the resulting traversibles + * is the same as in the original traversible. + */ + def partition(p: A => Boolean): (This, This) = { + val l, r = newBuilder + for (x <- this) (if (p(x)) l else r) += x + (l.result, r.result) + } + + /** Partion this traversible into a map of traversibles + * according to some discriminator function. + * @invariant (xs partition f)(k) = xs filter (x => f(x) == k) + * + * @note This method is not re-implemented by views. This means + * when applied to a view it will always force the view and + * return a new collection. + */ + def groupBy[K](f: A => K): Map[K, This] = { + var m = Map[K, Builder[A, This, Any]]() + for (elem <- this) { + val key = f(elem) + val bldr = m get key match { + case None => val b = newBuilder; m = m add (key, b); b + case Some(b) => b + } + bldr += elem + } + m mapValues (_.result) + } + + /** Apply a function <code>f</code> to all elements of this + * traversible object. + * + * @param f a function that is applied to every element. + * @note This method underlies the implementation of most other bulk operations. + * It should be overridden in concrete collection classes with efficient implementations. + */ + def foreach(f: A => Unit): Unit + + /** Return true iff the given predicate `p` yields true for all elements + * of this traversible. + * + * @note May not terminate for infinite-sized collections. + * @param p the predicate + */ + def forall(p: A => Boolean): Boolean = { + var result = true + breakable { + for (x <- this) + if (!p(x)) { result = false; break } + } + result + } + + /** Return true iff there is an element in this traversible for which the + * given predicate `p` yields true. + * + * @note May not terminate for infinite-sized collections. + * @param p the predicate + */ + def exists(p: A => Boolean): Boolean = { + var result = false + breakable { + for (x <- this) + if (p(x)) { result = true; break } + } + result + } + + /** Count the number of elements in the traversible which satisfy a predicate. + * + * @note Will not terminate for infinite-sized collections. + * @param p the predicate for which to count + * @return the number of elements satisfying the predicate <code>p</code>. + */ + def count(p: A => Boolean): Int = { + var cnt = 0 + for (x <- this) { + if (p(x)) cnt += 1 + } + cnt + } + + /** Find and return the first element of the traversible object satisfying a + * predicate, if any. + * + * @note may not terminate for infinite-sized collections. + * @note Might return different results for different runs, unless this traversible is ordered. + * @param p the predicate + * @return an option containing the first element in the traversible object + * satisfying <code>p</code>, or <code>None</code> if none exists. + */ + def find(p: A => Boolean): Option[A] = { + var result: Option[A] = None + breakable { + for (x <- this) + if (p(x)) { result = Some(x); break } + } + result + } + + /** Combines the elements of this traversible object together using the binary + * function <code>f</code>, from left to right, and starting with + * the value <code>z</code>. + * + * @note Will not terminate for infinite-sized collections. + * @note Might return different results for different runs, unless this traversible is ordered, or + * the operator is associative and commutative. + * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...), + * a<sub>n</sub>)</code> if the traversible is + * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>. + */ + def foldLeft[B](z: B)(op: (B, A) => B): B = { + var result = z + for (x <- this) + result = op(result, x) + result + } + + /** Similar to <code>foldLeft</code> but can be used as + * an operator with the order of traversible and zero arguments reversed. + * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code> + * @note Will not terminate for infinite-sized collections. + * @note Might return different results for different runs, unless this traversible is ordered, or + * the operator is associative and commutative. + */ + def /: [B](z: B)(op: (B, A) => B): B = foldLeft(z)(op) + + /** Combines the elements of this iterable together using the binary + * function <code>f</code>, from right to left, and starting with + * the value <code>z</code>. + * + * @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 <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code> + * if the iterable is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>. + */ + def foldRight[B](z: B)(op: (A, B) => B): B = { + var elems: List[A] = Nil + for (x <- this) elems = x :: elems + elems.foldLeft(z)((x, y) => op(y, x)) + } + + /** An alias for <code>foldRight</code>. + * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code> + * @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. + */ + def :\ [B](z: B)(op: (A, B) => B): B = foldRight(z)(op) + + /** Combines the elements of this traversible object together using the binary + * operator <code>op</code>, from left to right + * @note Will not terminate for infinite-sized collections. + * @note Might return different results for different runs, unless this traversible is ordered, or + * the operator is associative and commutative. + * @param op The operator to apply + * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code> + if the traversible object has elements + * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>. + * @throws Predef.UnsupportedOperationException if the traversible object is empty. + */ + def reduceLeft[B >: A](op: (B, A) => B): B = { + if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft") + var result: B = head + var first = true + for (x <- this) + if (first) first = false + else result = op(result, x) + result + } + + /** Combines the elements of this traversible object together using the binary + * operator <code>op</code>, from left to right + * @note Will not terminate for infinite-sized collections. + * @note Might return different results for different runs, unless this traversible is ordered, or + * the operator is associative and commutative. + * @param op The operator to apply + * @return If the traversible is non-empty, the result of the operations as an Option, otherwise None. + */ + def reduceLeftOpt[B >: A](op: (B, A) => B): Option[B] = { + if (isEmpty) None else Some(reduceLeft(op)) + } + + /** Combines the elements of this iterable object together using the binary + * operator <code>op</code>, 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 + * + * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code> + * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., + * a<sub>n</sub></code>. + * + * @throws Predef.UnsupportedOperationException if the iterator is empty. + */ + def reduceRight[B >: A](op: (A, B) => B): B = { + if (isEmpty) throw new UnsupportedOperationException("empty.reduceRight") + var elems: List[A] = Nil + for (x <- this) elems = x :: elems + elems.reduceLeft[B]((x, y) => op(y, x)) + } + + /** Combines the elements of this iterable object together using the binary + * operator <code>op</code>, 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 + * @return If the iterable is non-empty, the result of the operations as an Option, otherwise None. + */ + def reduceRightOpt[B >: A](op: (A, B) => B): Option[B] = { + if (isEmpty) None else Some(reduceRight(op)) + } + + /** The first element of this traversible. + * + * @note Might return different results for different runs, unless this traversible is ordered + * @throws Predef.NoSuchElementException if the traversible is empty. + */ + def head: A = { + var result: () => A = () => throw new NoSuchElementException + breakable { + for (x <- this) { + result = () => x + break + } + } + result() + } + + /** Returns as an option the first element of this traversible + * or <code>None</code> if traversible is empty. + * @note Might return different results for different runs, unless this traversible is ordered + */ + def headOption: Option[A] = if (isEmpty) None else Some(head) + + /** An traversible consisting of all elements of this traversible + * except the first one. + * @note Might return different results for different runs, unless this traversible is ordered + */ + def tail: This = drop(1) + + /** The last element of this traversible. + * + * @throws Predef.NoSuchElementException if the traversible is empty. + * @note Might return different results for different runs, unless this traversible is ordered + */ + def last: A = { + var lst = head + for (x <- this) + lst = x + lst + } + + /** Returns as an option the last element of this traversible or + * <code>None</code> if traversible is empty. + * + * @return the last element as an option. + * @note Might return different results for different runs, unless this traversible is ordered + */ + def lastOption: Option[A] = if (isEmpty) None else Some(last) + + /** An traversible consisting of all elements of this traversible except the last one. + * @throws Predef.UnsupportedOperationException if the stream is empty. + * @note Might return different results for different runs, unless this traversible is ordered + */ + def init: This = { + if (isEmpty) throw new UnsupportedOperationException("empty.init") + var lst = head + var follow = false + val b = newBuilder + for (x <- this) { + if (follow) b += lst + else follow = true + lst = x + } + b.result + } + + /** Return an traversible consisting only of the first <code>n</code> + * elements of this traversible, or else the whole traversible, if it has less + * than <code>n</code> elements. + * + * @param n the number of elements to take + * @note Might return different results for different runs, unless this traversible is ordered + */ + def take(n: Int): This = { + val b = newBuilder + var i = 0 + breakable { + for (x <- this) { + b += x + i += 1 + if (i == n) break + } + } + b.result + } + + /** Returns this traversible without its <code>n</code> first elements + * If this traversible has less than <code>n</code> elements, the empty + * traversible is returned. + * + * @param n the number of elements to drop + * @return the new traversible + * @note Might return different results for different runs, unless this traversible is ordered + */ + def drop(n: Int): This = { + val b = newBuilder + var i = 0 + for (x <- this) { + if (i >= n) b += x + i += 1 + } + b.result + } + + /** A sub-traversible 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 traversible is ordered + */ + def slice(from: Int, until: Int): This = { + val b = newBuilder + var i = 0 + breakable { + for (x <- this) { + if (i >= from) b += x + i += 1 + if (i == until) break + } + } + b.result + } + + /** Returns the longest prefix of this traversible whose elements satisfy + * the predicate <code>p</code>. + * + * @param p the test predicate. + * @note Might return different results for different runs, unless this traversible is ordered + */ + def takeWhile(p: A => Boolean): This = { + val b = newBuilder + breakable { + for (x <- this) { + if (!p(x)) break + b += x + } + } + b.result + } + + /** Returns the longest suffix of this traversible whose first element + * does not satisfy the predicate <code>p</code>. + * + * @param p the test predicate. + * @note Might return different results for different runs, unless this traversible is ordered + */ + def dropWhile(p: A => Boolean): This = { + val b = newBuilder + var go = false + for (x <- this) { + if (!p(x)) go = true + if (go) b += x + } + b.result + } + + /** Returns a pair consisting of the longest prefix of the traversible whose + * elements all satisfy the given predicate, and the rest of the traversible. + * + * @param p the test predicate + * @return a pair consisting of the longest prefix of the traversible whose + * elements all satisfy <code>p</code>, and the rest of the traversible. + * @note Might return different results for different runs, unless this traversible is ordered + */ + def span(p: A => Boolean): (This, This) = { + val l, r = newBuilder + var toLeft = true + for (x <- this) { + toLeft = toLeft && p(x) + (if (toLeft) l else r) += x + } + (l.result, r.result) + } + + /** Split the traversible at a given point and return the two parts thus + * created. + * + * @param n the position at which to split + * @return a pair of traversibles composed of the first <code>n</code> + * elements, and the other elements. + * @note Might return different results for different runs, unless this traversible is ordered + */ + def splitAt(n: Int): (This, This) = { + val l, r = newBuilder + var i = 0 + for (x <- this) { + (if (i < n) l else r) += x + i += 1 + } + (l.result, r.result) + } + + /** Copy all elements of this traversible to a given buffer + * @note Will not terminate for infinite-sized collections. + * @param dest The buffer to which elements are copied + */ + def copyToBuffer[B >: A](dest: Buffer[B]) { + for (x <- this) dest += x + } + + /** Fills the given array <code>xs</code> with at most `len` elements of + * this traversible starting at position `start`. + * Copying will stop once either the end of the current traversible 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 + */ + def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) { + var i = start + val end = (start + len) min xs.length + breakable { + for (x <- this) { + if (i >= end) break + xs(i) = x + i += 1 + } + } + } + + /** Fills the given array <code>xs</code> with the elements of + * this traversible starting at position <code>start</code> + * until either the end of the current traversible or the end of array `xs` is reached. + * + * @note Will not terminate for infinite-sized collections. + * @param xs the array to fill. + * @param start starting index. + * @pre the array must be large enough to hold all elements. + */ + def copyToArray[B >: A](xs: Array[B], start: Int) { + copyToArray(xs, start, xs.length - start) + } + + /** Converts this traversible to a fresh Array containing all elements. + * @note Will not terminate for infinite-sized collections. + */ + def toArray[B >: A]: Array[B] = { + val result = new Array[B](size) + copyToArray(result, 0) + result + } + + /** Returns a list with all elements of this traversible object. + * @note Will not terminate for infinite-sized collections. + */ + def toList: List[A] = (new ListBuffer[A] ++ thisCollection).toList + + /** Returns an iterable with all elements in this traversible object. + * @note Will not terminate for infinite-sized collections. + */ + def toIterable: Iterable[A] = toStream + + /** Returns a sequence with all elements in this traversible object. + * @note Will not terminate for infinite-sized collections. + */ + def toSequence: Sequence[A] = toList + + /** Returns a stream with all elements in this traversible object. + */ + def toStream: Stream[A] = toList.toStream + + /** Sort the traversible according to the comparison function + * <code><(e1: a, e2: a) => Boolean</code>, + * which should be true iff <code>e1</code> is smaller than + * <code>e2</code>. + * The sort is stable. That is elements that are equal wrt `lt` appear in the + * same order in the sorted traversible as in the original. + * + * @param lt the comparison function + * @return a traversible sorted according to the comparison function + * <code><(e1: a, e2: a) => Boolean</code>. + * @ex <pre> + * List("Steve", "Tom", "John", "Bob") + * .sort((e1, e2) => (e1 compareTo e2) < 0) = + * List("Bob", "John", "Steve", "Tom")</pre> + * !!! + def sortWith(lt : (A,A) => Boolean): This = { + val arr = toArray + Array.sortWith(arr, lt) + val b = newBuilder[A] + for (x <- arr) b += x + b.result + } + */ + + /** Returns a string representation of this traversible object. The resulting string + * begins with the string <code>start</code> and is finished by the string + * <code>end</code>. Inside, the string representations of elements (w.r.t. + * the method <code>toString()</code>) are separated by the string + * <code>sep</code>. + * + * @ex <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code> + * @param start starting string. + * @param sep separator string. + * @param end ending string. + * @return a string representation of this traversible object. + */ + def mkString(start: String, sep: String, end: String): String = + addString(new StringBuilder(), start, sep, end).toString + + /** Returns a string representation of this traversible object. The string + * representations of elements (w.r.t. the method <code>toString()</code>) + * are separated by the string <code>sep</code>. + * + * @param sep separator string. + * @return a string representation of this traversible object. + */ + def mkString(sep: String): String = + addString(new StringBuilder(), sep).toString + + /** Returns a string representation of this traversible object. The string + * representations of elements (w.r.t. the method <code>toString()</code>) + * follow each other without any separator string. + */ + def mkString: String = + addString(new StringBuilder()).toString + + /** Write all elements of this traversible into given string builder. + * The written text begins with the string <code>start</code> and is finished by the string + * <code>end</code>. Inside, the string representations of elements (w.r.t. + * the method <code>toString()</code>) are separated by the string + * <code>sep</code>. + */ + def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = { + b append start + var first = true + for (x <- this) { + if (first) first = false + else b append sep + b append x + } + b append end + } + + /** Write all elements of this string into given string builder. + * The string representations of elements (w.r.t. the method <code>toString()</code>) + * are separated by the string <code>sep</code>. + */ + def addString(b: StringBuilder, sep: String): StringBuilder = addString(b, "", sep, "") + + /** Write all elements of this string into given string builder without using + * any separator between consecutive elements. + */ + def addString(b: StringBuilder): StringBuilder = addString(b, "") + + override def toString = mkString(stringPrefix + "(", ", ", ")") + + /** Defines the prefix of this object's <code>toString</code> representation. + */ + def stringPrefix : String = { + var string = thisCollection.getClass.getName + val idx1 = string.lastIndexOf('.' : Int) + if (idx1 != -1) string = string.substring(idx1 + 1) + val idx2 = string.indexOf('$') + if (idx2 != -1) string = string.substring(0, idx2) + string + } + + /** Creates a view of this traversible @see TraversibleView + */ + def view = new TraversibleView[A, This] { + protected lazy val underlying = self.thisCollection + override def foreach(f: A => Unit) = self foreach f + } + + /** A sub-traversible 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) + */ + def view(from: Int, until: Int): TraversibleView[A, This] = view.slice(from, until) +} + + diff --git a/src/library/scala/collection/generic/TraversibleView.scala b/src/library/scala/collection/generic/TraversibleView.scala new file mode 100755 index 0000000000..8c45e9690d --- /dev/null +++ b/src/library/scala/collection/generic/TraversibleView.scala @@ -0,0 +1,29 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.collection.generic + +import Math.MAX_INT +import TraversibleView.NoBuilder + +/** A base class for views of Traversible. + * Every subclass has to implenment the foreach method + * @author Martin Odersky + * @version 2.8 + */ +trait TraversibleView[+A, +Coll <: Traversible[_]] extends TraversibleViewTemplate[A, Coll, TraversibleView[A, Coll]] + +object TraversibleView { + class NoBuilder[A] extends Builder[A, Nothing, TraversibleView[_, _]] { + def +=(elem: A) {} + def elements: Iterator[A] = Iterator.empty + def result() = throw new UnsupportedOperationException("TraversibleView.Builder.result") + def clear() {} + } + type Coll = TraversibleView[_, _] + implicit def builderFactory[A]: BuilderFactory[A, TraversibleView[A, Traversible[_]], Coll] = new BuilderFactory[A, TraversibleView[A, Traversible[_]], Coll] { def apply(from: Coll) = new NoBuilder } +} diff --git a/src/library/scala/collection/generic/TraversibleView.scala.1 b/src/library/scala/collection/generic/TraversibleView.scala.1 new file mode 100755 index 0000000000..c0999f9b9c --- /dev/null +++ b/src/library/scala/collection/generic/TraversibleView.scala.1 @@ -0,0 +1,145 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scalay.collection.generic + +import Math.MAX_INT +import TraversibleView.NoBuilder + +/** A base class for views of Traversible. + * Every subclass has to implenment the foreach method + */ +abstract class TraversibleView[+A, +Coll <: Traversible[_]] extends Traversible[A] { +self => + + type This >: this.type <: TraversibleView[A, Coll] { type This = self.This } + protected val thisCollection: This = this + + protected[this] def newBuilder: Builder[A, This, This] = + throw new UnsupportedOperationException(this+".newBuilder") + + def force[B >: A, That](implicit b: Builder[B, That, Coll]) = { + b ++= this + b.result() + } + + trait Transformed[+B] extends TraversibleView[B, Coll] + + /** pre: from >= 0 + */ + trait Sliced extends Transformed[A] { + protected[this] val from: Int + protected[this] val until: Int + override def foreach(f: A => Unit) { + var index = 0 + for (x <- self) { + if (from <= index) { + if (until <= index) return + f(x) + } + index += 1 + } + } + override def stringPrefix = self.stringPrefix+"S" + override def slice(from1: Int, until1: Int) = + newSliced(from + (from1 max 0), from + (until1 max 0)).asInstanceOf[This] + } + + trait Mapped[B] extends Transformed[B] { + protected[this] val mapping: A => B + override def foreach(f: B => Unit) { + for (x <- self) + f(mapping(x)) + } + override def stringPrefix = self.stringPrefix+"M" + } + + trait FlatMapped[B] extends Transformed[B] { + protected[this] val mapping: A => Traversible[B] + override def foreach(f: B => Unit) { + for (x <- self) + for (y <- mapping(x)) + f(y) + } + override def stringPrefix = self.stringPrefix+"N" + } + + trait Appended[B >: A] extends Transformed[B] { + protected[this] val rest: Traversible[B] + override def foreach(f: B => Unit) { + for (x <- self) f(x) + for (x <- rest) f(x) + } + override def stringPrefix = self.stringPrefix+"A" + } + + trait Filtered extends Transformed[A] { + protected[this] val pred: A => Boolean + override def foreach(f: A => Unit) { + for (x <- self) + if (pred(x)) f(x) + } + override def stringPrefix = self.stringPrefix+"F" + } + + trait TakenWhile extends Transformed[A] { + protected[this] val pred: A => Boolean + override def foreach(f: A => Unit) { + for (x <- self) { + if (!pred(x)) return + f(x) + } + } + override def stringPrefix = self.stringPrefix+"T" + } + + trait DroppedWhile extends Transformed[A] { + protected[this] val pred: A => Boolean + override def foreach(f: A => Unit) { + var go = false + for (x <- self) { + if (!go && !pred(x)) go = true + if (go) f(x) + } + } + override def stringPrefix = self.stringPrefix+"D" + } + + override def ++[B >: A, That](that: Traversible[B])(implicit b: Builder[B, That, This]): That = + if (b.isInstanceOf[NoBuilder[_]]) newAppended(that).asInstanceOf[That] + else super.++[B, That](that)(b) + + override def ++[B >: A, That](that: Iterator[B])(implicit b: Builder[B, That, This]): That = ++[B, That](that.toStream) + + override def map[B, That](f: A => B)(implicit b: Builder[B, That, This]): That = + if (b.isInstanceOf[NoBuilder[_]]) newMapped(f).asInstanceOf[That] + else super.map[B, That](f)(b) + + override def flatMap[B, That](f: A => Traversible[B])(implicit b: Builder[B, That, This]): That = + if (b.isInstanceOf[NoBuilder[_]]) newFlatMapped(f).asInstanceOf[That] + else super.flatMap[B, That](f)(b) + + override def filter(p: A => Boolean): This = newFiltered(p).asInstanceOf[This] + override def init: This = newSliced(0, size - 1).asInstanceOf[This] + override def drop(n: Int): This = newSliced(n max 0, MAX_INT).asInstanceOf[This] + override def take(n: Int): This = newSliced(0, n).asInstanceOf[This] + override def slice(from: Int, until: Int): This = newSliced(from max 0, until).asInstanceOf[This] + override def dropWhile(p: A => Boolean): This = newDroppedWhile(p).asInstanceOf[This] + override def takeWhile(p: A => Boolean): This = newTakenWhile(p).asInstanceOf[This] + override def span(p: A => Boolean): (This, This) = (takeWhile(p), dropWhile(p)) + override def splitAt(n: Int): (This, This) = (take(n), drop(n)) +} + +object TraversibleView { + class NoBuilder[A] extends Builder[A, Nothing, TraversibleView[_, _]] { + def +=(elem: A) {} + def elements: Iterator[A] = Iterator.empty + def result() = throw new UnsupportedOperationException("TraversibleView.Builder.result") + def clear() {} + } + implicit def implicitBuilder[A]: Builder[A, TraversibleView[A, Traversible[_]], TraversibleView[_, _]] = new NoBuilder +} diff --git a/src/library/scala/collection/generic/TraversibleViewTemplate.scala b/src/library/scala/collection/generic/TraversibleViewTemplate.scala new file mode 100755 index 0000000000..7cb84d5cfc --- /dev/null +++ b/src/library/scala/collection/generic/TraversibleViewTemplate.scala @@ -0,0 +1,160 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.collection.generic + +import Math.MAX_INT +import TraversibleView.NoBuilder + +/** A base class for views of Traversible. + * Every subclass has to implenment the foreach method + * @author Martin Odersky + * @version 2.8 + */ +trait TraversibleViewTemplate[+A, + +Coll <: Traversible[_], + +This <: TraversibleView[A, Coll] with TraversibleViewTemplate[A, Coll, This]] + extends Traversible[A] with TraversibleTemplate[A, This] { +self => + + override protected[this] def newBuilder: Builder[A, This, Any] = + throw new UnsupportedOperationException(this+".newBuilder") + + protected def underlying: Coll + + def force[B >: A, That](implicit bf: BuilderFactory[B, That, Coll]) = { + val b = bf(underlying) + b ++= this + b.result() + } + + trait Transformed[+B] extends TraversibleView[B, Coll] { + lazy val underlying = self.underlying + } + + /** pre: from >= 0 + */ + trait Sliced extends Transformed[A] { + protected[this] val from: Int + protected[this] val until: Int + override def foreach(f: A => Unit) { + var index = 0 + for (x <- self) { + if (from <= index) { + if (until <= index) return + f(x) + } + index += 1 + } + } + override def stringPrefix = self.stringPrefix+"S" + override def slice(from1: Int, until1: Int): This = + newSliced(from + (from1 max 0), from + (until1 max 0)).asInstanceOf[This] + } + + trait Mapped[B] extends Transformed[B] { + protected[this] val mapping: A => B + override def foreach(f: B => Unit) { + for (x <- self) + f(mapping(x)) + } + override def stringPrefix = self.stringPrefix+"M" + } + + trait FlatMapped[B] extends Transformed[B] { + protected[this] val mapping: A => Traversible[B] + override def foreach(f: B => Unit) { + for (x <- self) + for (y <- mapping(x)) + f(y) + } + override def stringPrefix = self.stringPrefix+"N" + } + + trait Appended[B >: A] extends Transformed[B] { + protected[this] val rest: Traversible[B] + override def foreach(f: B => Unit) { + for (x <- self) f(x) + for (x <- rest) f(x) + } + override def stringPrefix = self.stringPrefix+"A" + } + + trait Filtered extends Transformed[A] { + protected[this] val pred: A => Boolean + override def foreach(f: A => Unit) { + for (x <- self) + if (pred(x)) f(x) + } + override def stringPrefix = self.stringPrefix+"F" + } + + trait TakenWhile extends Transformed[A] { + protected[this] val pred: A => Boolean + override def foreach(f: A => Unit) { + for (x <- self) { + if (!pred(x)) return + f(x) + } + } + override def stringPrefix = self.stringPrefix+"T" + } + + trait DroppedWhile extends Transformed[A] { + protected[this] val pred: A => Boolean + override def foreach(f: A => Unit) { + var go = false + for (x <- self) { + if (!go && !pred(x)) go = true + if (go) f(x) + } + } + override def stringPrefix = self.stringPrefix+"D" + } + + /** Boilerplate method, to override in each subclass + * This method could be eliminated if Scala had virtual classes + */ + protected def newAppended[B >: A](that: Traversible[B]): Transformed[B] = new Appended[B] { val rest = that } + protected def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f } + protected def newFlatMapped[B](f: A => Traversible[B]): Transformed[B] = new FlatMapped[B] { val mapping = f } + protected def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p } + protected def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until } + protected def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p } + protected def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p } + + override def ++[B >: A, That](that: Traversible[B])(implicit bf: BuilderFactory[B, That, This]): That = { + val b = bf(thisCollection) + if (b.isInstanceOf[NoBuilder[_]]) newAppended(that).asInstanceOf[That] + else super.++[B, That](that)(bf) + } + + override def ++[B >: A, That](that: Iterator[B])(implicit bf: BuilderFactory[B, That, This]): That = ++[B, That](that.toStream) + + override def map[B, That](f: A => B)(implicit bf: BuilderFactory[B, That, This]): That = { + val b = bf(thisCollection) + if (b.isInstanceOf[NoBuilder[_]]) newMapped(f).asInstanceOf[That] + else super.map[B, That](f)(bf) + } + + override def flatMap[B, That](f: A => Traversible[B])(implicit bf: BuilderFactory[B, That, This]): That = { + val b = bf(thisCollection) + if (b.isInstanceOf[NoBuilder[_]]) newFlatMapped(f).asInstanceOf[That] + else super.flatMap[B, That](f)(bf) + } + + override def filter(p: A => Boolean): This = newFiltered(p).asInstanceOf[This] + override def init: This = newSliced(0, size - 1).asInstanceOf[This] + override def drop(n: Int): This = newSliced(n max 0, MAX_INT).asInstanceOf[This] + override def take(n: Int): This = newSliced(0, n).asInstanceOf[This] + override def slice(from: Int, until: Int): This = newSliced(from max 0, until).asInstanceOf[This] + override def dropWhile(p: A => Boolean): This = newDroppedWhile(p).asInstanceOf[This] + override def takeWhile(p: A => Boolean): This = newTakenWhile(p).asInstanceOf[This] + override def span(p: A => Boolean): (This, This) = (takeWhile(p), dropWhile(p)) + override def splitAt(n: Int): (This, This) = (take(n), drop(n)) +} + diff --git a/src/library/scalax/collection/generic/covartest/VectorTemplate.scala b/src/library/scala/collection/generic/VectorTemplate.scala index 8c28077ea3..96c9e125dc 100644..100755 --- a/src/library/scalax/collection/generic/covartest/VectorTemplate.scala +++ b/src/library/scala/collection/generic/VectorTemplate.scala @@ -8,39 +8,46 @@ // $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $ -package scalax.collection.generic.covartest +package scala.collection.generic -import Vector._ +import mutable.ArrayBuffer /** Sequences that support O(1) element access and O(1) length computation. + * This class does not add any methods to Sequence but overrides several + * methods with optimized implementations. + * * @author Sean McDirmid * @author Martin Odersky * @version 2.8 */ -trait VectorTemplate[+CC[+B] <: VectorTemplate[CC, B] with Vector[B], +A] extends SequenceTemplate[CC, A] { -self => +trait VectorTemplate[+A, +This <: VectorTemplate[A, This] with Vector[A]] extends SequenceTemplate[A, This] { self => // Overridden methods from IterableTemplate /** The iterator returned by the elements method */ - protected class Elements(start: Int, end: Int) extends scalax.collection.BufferedIterator[A] { - var i = start + protected class Elements(start: Int, end: Int) extends scala.collection.BufferedIterator[A] { + private var i = start + def hasNext: Boolean = i < end + def next: A = if (i < end) { val x = self(i) i += 1 x } else Iterator.empty.next + def head = if (i < end) self(i) else Iterator.empty.next + /** drop is overridden to enable fast searching in the middle of random access sequences */ override def drop(n: Int): Iterator[A] = if (n > 0) new Elements(start + n, end) else this - /** is overridden to be symmetric to drop */ + + /** take is overridden to be symmetric to drop */ override def take(n: Int): Iterator[A] = - if (n < 0) Iterator.empty.buffered + if (n <= 0) Iterator.empty.buffered else if (start + n < end) new Elements(start, start + n) else this } @@ -78,53 +85,35 @@ self => if (start == len) z else op(this(start), foldr(start + 1, len, z, op)) - override def foldLeft[B](z: B)(op: (B, A) => B): B = foldl(0, z, op) - override def foldRight[B](z: B)(op: (A, B) => B): B = foldr(0, length, z, op) + override def foldLeft[B](z: B)(op: (B, A) => B): B = + foldl(0, z, op) + override def foldRight[B](z: B)(op: (A, B) => B): B = + foldr(0, length, z, op) override def reduceLeft[B >: A](op: (B, A) => B): B = - if (length > 0) foldl(0, this(0), op) else super.reduceLeft(op) + if (length > 0) foldl(1, this(0), op) else super.reduceLeft(op) override def reduceRight[B >: A](op: (A, B) => B): B = if (length > 0) foldr(0, length - 1, this(length - 1), op) else super.reduceRight(op) - override def zip[B](that: Iterable[B]): CC[(A, B)] = that match { - case that: Vector[_] => - var i = 0 - val len = this.length min that.length - val b = this.newBuilder[(A, B)] - while (i < len) { - b += ((this(i), that(i).asInstanceOf[B])) - i += 1 - } - b.result - case _ => - super.zip(that) - } - - override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): CC[(A1, B1)] = that match { + override def zip[A1 >: A, B, That](that: Sequence[B])(implicit bf: BuilderFactory[(A1, B), That, This]): That = that match { case that: Vector[_] => + val b = bf(thisCollection) var i = 0 val len = this.length min that.length - val b = this.newBuilder[(A1, B1)] + b.sizeHint(len) while (i < len) { b += ((this(i), that(i).asInstanceOf[B])) i += 1 } - while (i < this.length) { - b += ((this(i), thatElem)) - i += 1 - } - while (i < that.length) { - b += ((this(i), thatElem.asInstanceOf[B])) - i += 1 - } b.result case _ => - super.zipAll(that, thisElem, thatElem) + super.zip[A1, B, That](that)(bf) } - override def zipWithIndex: CC[(A, Int)] = { - val b = newBuilder[(A, Int)] - var i = 0 + override def zipWithIndex[A1 >: A, That](implicit bf: BuilderFactory[(A1, Int), That, This]): That = { + val b = bf(thisCollection) val len = length + b.sizeHint(len) + var i = 0 while (i < len) { b += ((this(i), i)) i += 1 @@ -132,25 +121,11 @@ self => b.result } - override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) { - var i = 0 - var j = start - val end = length min len min (xs.length - start) - while (i < end) { - xs(j) = this(i) - i += 1 - j += 1 - } - } - - // Overridden methods from OrderedIterableTemplate - - override def head: A = if (isEmpty) throw new NoSuchElementException else this(0) - - override def slice(from: Int, until: Int): CC[A] = { - val b = newBuilder[A] + override def slice(from: Int, until: Int): This = { var i = from max 0 val end = until min length + val b = newBuilder + b.sizeHint(end - i) while (i < end) { b += this(i) i += 1 @@ -158,18 +133,20 @@ self => b.result } - override def take(n: Int): CC[A] = slice(0, n) - override def drop(n: Int): CC[A] = slice(n, length) - override def takeRight(n: Int): CC[A] = slice(length - n, length) - override def dropRight(n: Int): CC[A] = slice(0, length - n) - override def splitAt(n: Int): (CC[A], CC[A]) = (take(n), drop(n)) - override def takeWhile(p: A => Boolean): CC[A] = take(prefixLength(p)) - override def dropWhile(p: A => Boolean): CC[A] = drop(prefixLength(p)) - override def span(p: A => Boolean): (CC[A], CC[A]) = splitAt(prefixLength(p)) + override def head: A = if (isEmpty) super.head else this(0) + override def tail: This = slice(1, length) override def last: A = if (length > 0) this(length - 1) else super.last - override def init: CC[A] = if (length > 0) slice(0, length - 1) else super.init - - override def sameElements[B >: A](that: OrderedIterable[B]): Boolean = that match { + override def init: This = if (length > 0) slice(0, length - 1) else super.init + override def take(n: Int): This = slice(0, n) + override def drop(n: Int): This = slice(n, length) + override def takeRight(n: Int): This = slice(length - n, length) + override def dropRight(n: Int): This = slice(0, length - n) + override def splitAt(n: Int): (This, This) = (take(n), drop(n)) + override def takeWhile(p: A => Boolean): This = take(prefixLength(p)) + override def dropWhile(p: A => Boolean): This = drop(prefixLength(p)) + override def span(p: A => Boolean): (This, This) = splitAt(prefixLength(p)) + + override def sameElements[B >: A](that: Iterable[B]): Boolean = that match { case that: Vector[_] => val len = length len == that.length && { @@ -181,14 +158,35 @@ self => super.sameElements(that) } + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) { + var i = 0 + var j = start + val end = length min len min (xs.length - start) + while (i < end) { + xs(j) = this(i) + i += 1 + j += 1 + } + } + // Overridden methods from Sequence override def lengthCompare(len: Int): Int = length - len + override def segmentLength(p: A => Boolean, from: Int): Int = { + val start = from + val len = length + var i = start + while (i < len && p(this(i))) i += 1 + i - start + } + private def negLength(n: Int) = if (n == length) -1 else n - override def indexWhere(p: A => Boolean, from: Int): Int = - negLength(from + segmentLength(!p(_), from)) + override def indexWhere(p: A => Boolean, from: Int): Int = { + val start = from max 0 + negLength(start + segmentLength(!p(_), start)) + } override def lastIndexWhere(p: A => Boolean, end: Int): Int = { var i = end @@ -196,10 +194,9 @@ self => i } - override def lastIndexOf[B >: A](elem: B, end: Int): Int = lastIndexWhere(elem ==, end) - - override def reverse: CC[A] = { - val b = newBuilder[A] + override def reverse: This = { + val b = newBuilder + b.sizeHint(length) var i = length while (0 < i) { i -= 1 @@ -209,7 +206,7 @@ self => } override def reversedElements: Iterator[A] = new Iterator[A] { - var i = length + private var i = self.length def hasNext: Boolean = 0 < i def next: A = if (0 < i) { @@ -233,7 +230,7 @@ self => var i = offset val thisLen = length val thatElems = that.elements - while (i < thisLen && thatElems.hasNext && this(i) == thatElems.next) { + while (i < thisLen && thatElems.hasNext && this(i) == thatElems.next()) { i += 1 } !thatElems.hasNext @@ -254,11 +251,32 @@ self => super.endsWith(that) } - override def indexOf[B >: A](that: Sequence[B]): Int = { + override def indexOfSeq[B >: A](that: Sequence[B]): Int = { var i = 0 val last = length - that.length while (i <= last && !startsWith(that, i)) i += 1 negLength(i) } + + override def equals(that: Any): Boolean = that match { + case that1: Vector[a] => + val len = this.length + len == that1.length && { + var i = 0 + while (i < len && this(i) == that1(i)) i += 1 + i == len + } + case _ => + super.equals(that) + } + + override def view = new VectorView[A, This] { + protected lazy val underlying = self.thisCollection + override def elements = self.elements + override def length = self.length + override def apply(idx: Int) = self.apply(idx) + } + + override def view(from: Int, until: Int) = view.slice(from, until) } diff --git a/src/library/scala/collection/generic/VectorView.scala b/src/library/scala/collection/generic/VectorView.scala new file mode 100755 index 0000000000..5460ac9f70 --- /dev/null +++ b/src/library/scala/collection/generic/VectorView.scala @@ -0,0 +1,26 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ + + +package scala.collection.generic + +import TraversibleView.NoBuilder + +/** A non-strict projection of an iterable. + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ +trait VectorView[+A, +Coll <: Vector[_]] extends VectorViewTemplate[A, Coll, VectorView[A, Coll]] + +object VectorView { + type Coll = TraversibleView[_, _] + implicit def builderFactory[A]: BuilderFactory[A, VectorView[A, Vector[_]], Coll] = new BuilderFactory[A, VectorView[A, Vector[_]], Coll] { def apply(from: Coll) = new NoBuilder } +} diff --git a/src/library/scala/collection/generic/VectorViewTemplate.scala b/src/library/scala/collection/generic/VectorViewTemplate.scala new file mode 100755 index 0000000000..e8744a3230 --- /dev/null +++ b/src/library/scala/collection/generic/VectorViewTemplate.scala @@ -0,0 +1,80 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ + + +package scala.collection.generic + +import TraversibleView.NoBuilder + +/** A non-strict projection of an iterable. + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ +trait VectorViewTemplate[+A, + +Coll <: Vector[_], + +This <: VectorView[A, Coll] with VectorViewTemplate[A, Coll, This]] + extends Vector[A] with VectorTemplate[A, This] with SequenceView[A, Coll] with SequenceViewTemplate[A, Coll, This] +{ self => + + trait Transformed[+B] extends VectorView[B, Coll] with super.Transformed[B] + + trait Sliced extends Transformed[A] with super.Sliced { + /** Override to use Vector's foreach; todo: see whether this is really faster */ + override def foreach(f: A => Unit) = super[Transformed].foreach(f) + } + + trait Mapped[B] extends Transformed[B] with super.Mapped[B] { + override def foreach(f: B => Unit) = super[Transformed].foreach(f) + } + + trait FlatMapped[B] extends Transformed[B] with super.FlatMapped[B] { + override def foreach(f: B => Unit) = super[Transformed].foreach(f) + } + + trait Appended[B >: A] extends Transformed[B] with super.Appended[B] { + override def foreach(f: B => Unit) = super[Transformed].foreach(f) + } + + trait Filtered extends Transformed[A] with super.Filtered { + override def foreach(f: A => Unit) = super[Transformed].foreach(f) + } + + trait TakenWhile extends Transformed[A] with super.TakenWhile { + override def foreach(f: A => Unit) = super[Transformed].foreach(f) + } + + trait DroppedWhile extends Transformed[A] with super.DroppedWhile { + override def foreach(f: A => Unit) = super[Transformed].foreach(f) + } + + trait Reversed extends Transformed[A] with super.Reversed { + override def foreach(f: A => Unit) = super[Transformed].foreach(f) + } + + trait Patched[B >: A] extends Transformed[B] with super.Patched[B] { + override def foreach(f: B => Unit) = super[Transformed].foreach(f) + } + + /** Boilerplate method, to override in each subclass + * This method could be eliminated if Scala had virtual classes + */ + protected override def newAppended[B >: A](that: Traversible[B]): Transformed[B] = new Appended[B] { val rest = that } + protected override def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f } + protected override def newFlatMapped[B](f: A => Traversible[B]): Transformed[B] = new FlatMapped[B] { val mapping = f } + protected override def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p } + protected override def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until } + protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p } + protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p } + protected override def newReversed: Transformed[A] = new Reversed { } + protected override def newPatched[B >: A](_from: Int, _patch: Sequence[B], _replaced: Int): Transformed[B] = new Patched[B] { + val from = _from; val patch = _patch; val replaced = _replaced + } +} diff --git a/src/library/scala/collection/immutable/BitSet.scala b/src/library/scala/collection/immutable/BitSet.scala index eb276699bd..575d8dfd7d 100644 --- a/src/library/scala/collection/immutable/BitSet.scala +++ b/src/library/scala/collection/immutable/BitSet.scala @@ -11,43 +11,70 @@ package scala.collection.immutable +import BitSet._ +import generic._ -/** The class <code>BitSet</code> provides an immutable bitset view on an - * int array. Instances can conveniently be created from instances of - * Bit indices are between <code>0..(capacity-1)</code> inclusive. - * - * @param size <code>size</code> represents the number of relevant bits - * @param capacity ... - * @param ba <code>ba</code> array of ints of length - * <code>n>>>5</code> - * @param copy <code>copy</code> if yes, then <code>ba</code> is copied - * and updates will not affect this bitset - * - * @author Burak Emir, Nikolay Mihaylov - * @version 1.0 +/** a base class for immutable bit sets */ +abstract class BitSet extends Set[Int] with collection.BitSet with BitSetTemplate[BitSet] { + override def empty = BitSet.empty + def fromArray(elems: Array[Long]): BitSet = BitSet.fromArray(elems) +} -@serializable -/* - * This is a strange class! It claims to be immutable but is not. - * It claims to be a BitSet but it is not a Set. - * Remove it or integrate it into the Set hierarchy. - * [Comments by Martin] - */ -class BitSet(val size: Int, val capacity: Int, ba: Array[Int], copy: Boolean) - extends collection.BitSet -{ - import compat.Platform.arraycopy - - protected val arr: Array[Int] = { - val ba1 = if (ba != null) ba else new Array[Int](0) - if (copy) { - val arr = new Array[Int](ba1.length) - arraycopy(ba1, 0, arr, 0, ba1.length) - arr - } - else - ba1 +/** A factory object for bitsets */ +object BitSet { + + /** The empty bitset */ + val empty: BitSet = new BitSet1(0L) + + /** A bitset containing given elements */ + def apply(elems: Int*) = (empty /: elems) (_ + _) + + /** A bitset containing all the bits in an array */ + def fromArray(elems: Array[Long]): BitSet = { + val len = elems.length + if (len == 0) empty + else if (len == 1) new BitSet1(elems(0)) + else if (len == 2) new BitSet2(elems(0), elems(1)) + else new BitSetN(elems) + } + + private val hashSeed = "BitSet".hashCode + + private def updateArray(elems: Array[Long], idx: Int, w: Long): BitSet = { + var len = elems.length + while (len > 0 && (elems(len - 1) == 0L || w == 0L && idx == len - 1)) len -= 1 + var newlen = len + if (idx >= newlen && w != 0L) newlen = idx + 1 + val newelems = new Array[Long](newlen) + Array.copy(elems, 0, newelems, 0, len) + if (idx < newlen) newelems(idx) = w + else assert(w == 0L) + fromArray(newelems) + } + + class BitSet1(val elems: Long) extends BitSet { + protected def nwords = 1 + protected def word(idx: Int) = if (idx == 0) elems else 0L + protected def updateWord(idx: Int, w: Long): BitSet = + if (idx == 0) new BitSet1(w) + else if (idx == 1) new BitSet2(elems, w) + else updateArray(Array(elems), idx, w) } + class BitSet2(val elems0: Long, elems1: Long) extends BitSet { + protected def nwords = 2 + protected def word(idx: Int) = if (idx == 0) elems0 else if (idx == 1) elems1 else 0L + protected def updateWord(idx: Int, w: Long): BitSet = + if (idx == 0) new BitSet2(w, elems1) + else if (idx == 1) new BitSet2(elems0, w) + else updateArray(Array(elems0, elems1), idx, w) + } + + class BitSetN(val elems: Array[Long]) extends BitSet { + protected def nwords = elems.length + protected def word(idx: Int) = if (idx < nwords) elems(idx) else 0L + protected def updateWord(idx: Int, w: Long): BitSet = updateArray(elems, idx, w) + } } + diff --git a/src/library/scala/collection/immutable/EmptyMap.scala b/src/library/scala/collection/immutable/EmptyMap.scala deleted file mode 100644 index 70e0a766cd..0000000000 --- a/src/library/scala/collection/immutable/EmptyMap.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - - -package scala.collection.immutable - -import Predef.Pair - -/** This class implements empty immutable maps - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class EmptyMap[A, +B] extends Map[A, B] { - - def size: Int = 0 - - def get(key: A): Option[B] = None - - def elements: Iterator[(A, B)] = Iterator.empty - - def empty[C]: Map[A, C] = new EmptyMap[A, C] - - def update [B1 >: B](key: A, value: B1): Map[A, B1] = - new Map1(key, value) - - def - (key: A): Map[A, B] = this -} - - - diff --git a/src/library/scala/collection/immutable/FlexMap.scala b/src/library/scala/collection/immutable/FlexMap.scala new file mode 100755 index 0000000000..eb982734a3 --- /dev/null +++ b/src/library/scala/collection/immutable/FlexMap.scala @@ -0,0 +1,143 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Map.scala 16893 2009-01-13 13:09:22Z cunei $ + + +package scala.collection.immutable + +import generic._ + +/** A default implementation of immutable maps. + * This is implemented by specialized implementations + * `EmptyMap`, Map1, ..., Map4, for maps of size up to 4, and + * a proxy for an immutable HashMap for larger maps. + */ +trait FlexMap[A, +B] extends Map[A, B] { self => + override def empty: Map[A, B] = FlexMap.empty +} + +/* Factory object for `FlexMap class */ +object FlexMap extends ImmutableMapFactory[Map] { + def empty[A, B]: FlexMap[A, B] = new EmptyMap[A, B] + + @serializable + class EmptyMap[A, +B] extends FlexMap[A, B] { + override def size: Int = 0 + def get(key: A): Option[B] = None + def elements: Iterator[(A, B)] = Iterator.empty + def add [B1 >: B] (key: A, value: B1): Map[A, B1] = new Map1(key, value) + def - (key: A): Map[A, B] = this + } + + @serializable + class Map1[A, +B](key1: A, value1: B) extends FlexMap[A, B] { + override def size = 1 + def get(key: A): Option[B] = + if (key == key1) Some(value1) else None + def elements = Iterator((key1, value1)) + def add [B1 >: B] (key: A, value: B1): Map[A, B1] = + if (key == key1) new Map1(key1, value) + else new Map2(key1, value1, key, value) + def - (key: A): Map[A, B] = + if (key == key1) empty else this + override def foreach(f: ((A, B)) => Unit): Unit = { + f((key1, value1)) + } + } + + @serializable + class Map2[A, +B](key1: A, value1: B, key2: A, value2: B) extends FlexMap[A, B] { + override def size = 2 + def get(key: A): Option[B] = + if (key == key1) Some(value1) + else if (key == key2) Some(value2) + else None + def elements = Iterator((key1, value1), (key2, value2)) + def add [B1 >: B] (key: A, value: B1): Map[A, B1] = + if (key == key1) new Map2(key1, value, key2, value2) + else if (key == key2) new Map2(key1, value1, key2, value) + else new Map3(key1, value1, key2, value2, key, value) + def - (key: A): Map[A, B] = + if (key == key1) new Map1(key2, value2) + else if (key == key2) new Map1(key1, value1) + else this + override def foreach(f: ((A, B)) => Unit): Unit = { + f((key1, value1)); f((key2, value2)) + } + } + + @serializable + class Map3[A, +B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B) extends FlexMap[A, B] { + override def size = 3 + def get(key: A): Option[B] = + if (key == key1) Some(value1) + else if (key == key2) Some(value2) + else if (key == key3) Some(value3) + else None + def elements = Iterator((key1, value1), (key2, value2), (key3, value3)) + def add [B1 >: B] (key: A, value: B1): Map[A, B1] = + if (key == key1) new Map3(key1, value, key2, value2, key3, value3) + else if (key == key2) new Map3(key1, value1, key2, value, key3, value3) + else if (key == key3) new Map3(key1, value1, key2, value2, key3, value) + else new Map4(key1, value1, key2, value2, key3, value3, key, value) + def - (key: A): Map[A, B] = + if (key == key1) new Map2(key2, value2, key3, value3) + else if (key == key2) new Map2(key1, value1, key3, value3) + else if (key == key3) new Map2(key1, value1, key2, value2) + else this + override def foreach(f: ((A, B)) => Unit): Unit = { + f((key1, value1)); f((key2, value2)); f((key3, value3)) + } + } + + @serializable + class Map4[A, +B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B, key4: A, value4: B) extends FlexMap[A, B] { + override def size = 4 + def get(key: A): Option[B] = + if (key == key1) Some(value1) + else if (key == key2) Some(value2) + else if (key == key3) Some(value3) + else if (key == key4) Some(value4) + else None + def elements = Iterator((key1, value1), (key2, value2), (key3, value3), (key4, value4)) + def add [B1 >: B] (key: A, value: B1): Map[A, B1] = + if (key == key1) new Map4(key1, value, key2, value2, key3, value3, key4, value4) + else if (key == key2) new Map4(key1, value1, key2, value, key3, value3, key4, value4) + else if (key == key3) new Map4(key1, value1, key2, value2, key3, value, key4, value4) + else if (key == key4) new Map4(key1, value1, key2, value2, key3, value3, key4, value) + else new HashMap + ((key1, value1), (key2, value2), (key3, value3), (key4, value4), (key, value)) + def - (key: A): Map[A, B] = + if (key == key1) new Map3(key2, value2, key3, value3, key4, value4) + else if (key == key2) new Map3(key1, value1, key3, value3, key4, value4) + else if (key == key3) new Map3(key1, value1, key2, value2, key4, value4) + else if (key == key4) new Map3(key1, value1, key2, value2, key3, value3) + else this + override def foreach(f: ((A, B)) => Unit): Unit = { + f((key1, value1)); f((key2, value2)); f((key3, value3)); f((key4, value4)) + } + } +} + + + + + + + + + + + + + + + + + + diff --git a/src/library/scala/collection/immutable/FlexSet.scala b/src/library/scala/collection/immutable/FlexSet.scala new file mode 100755 index 0000000000..350ac96854 --- /dev/null +++ b/src/library/scala/collection/immutable/FlexSet.scala @@ -0,0 +1,120 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: HashSet.scala 16884 2009-01-09 16:52:09Z cunei $ + +package scala.collection.immutable + +import generic._ + +/** A default implementation of immutable sets. + * This is implemented by specialized implementations + * `EmptySet`, Set1, ..., Set4, for sets of size up to 4, and + * a proxy for an immutable HashSet for larger sets. + */ +trait FlexSet[A] extends Set[A] { self => + override def empty = FlexSet.empty +} + +/* Factory object for `FlexSet` class */ +object FlexSet extends SetFactory[Set] { + def empty[A]: FlexSet[A] = new EmptySet[A] + + /** An optimized representation for immutable empty sets */ + @serializable + class EmptySet[A] extends FlexSet[A] { + override def size: Int = 0 + def contains(elem: A): Boolean = false + def + (elem: A): Set[A] = new Set1(elem) + def - (elem: A): Set[A] = this + def elements: Iterator[A] = Iterator.empty + override def foreach(f: A => Unit): Unit = {} + } + + /** An optimized representation for immutable sets of size 1 */ + @serializable + class Set1[A](elem1: A) extends FlexSet[A] { + override def size: Int = 1 + def contains(elem: A): Boolean = + elem == elem1 + def + (elem: A): Set[A] = + if (contains(elem)) this + else new Set2(elem1, elem) + def - (elem: A): Set[A] = + if (elem == elem1) new EmptySet[A] + else this + def elements: Iterator[A] = + Iterator(elem1) + override def foreach(f: A => Unit): Unit = { + f(elem1) + } + } + + /** An optimized representation for immutable sets of size 2 */ + @serializable + class Set2[A](elem1: A, elem2: A) extends FlexSet[A] { + override def size: Int = 2 + def contains(elem: A): Boolean = + elem == elem1 || elem == elem2 + def + (elem: A): Set[A] = + if (contains(elem)) this + else new Set3(elem1, elem2, elem) + def - (elem: A): Set[A] = + if (elem == elem1) new Set1(elem2) + else if (elem == elem2) new Set1(elem1) + else this + def elements: Iterator[A] = + Iterator(elem1, elem2) + override def foreach(f: A => Unit): Unit = { + f(elem1); f(elem2) + } + } + + /** An optimized representation for immutable sets of size 3 */ + @serializable + class Set3[A](elem1: A, elem2: A, elem3: A) extends FlexSet[A] { + override def size: Int = 3 + def contains(elem: A): Boolean = + elem == elem1 || elem == elem2 || elem == elem3 + def + (elem: A): Set[A] = + if (contains(elem)) this + else new Set4(elem1, elem2, elem3, elem) + def - (elem: A): Set[A] = + if (elem == elem1) new Set2(elem2, elem3) + else if (elem == elem2) new Set2(elem1, elem3) + else if (elem == elem3) new Set2(elem1, elem2) + else this + def elements: Iterator[A] = + Iterator(elem1, elem2, elem3) + override def foreach(f: A => Unit): Unit = { + f(elem1); f(elem2); f(elem3) + } + } + + /** An optimized representation for immutable sets of size 4 */ + @serializable + class Set4[A](elem1: A, elem2: A, elem3: A, elem4: A) extends FlexSet[A] { + override def size: Int = 4 + def contains(elem: A): Boolean = + elem == elem1 || elem == elem2 || elem == elem3 || elem == elem4 + def + (elem: A): Set[A] = + if (contains(elem)) this + else new HashSet[A] + (elem1, elem2, elem3, elem4, elem) + def - (elem: A): Set[A] = + if (elem == elem1) new Set3(elem2, elem3, elem4) + else if (elem == elem2) new Set3(elem1, elem3, elem4) + else if (elem == elem3) new Set3(elem1, elem2, elem4) + else if (elem == elem4) new Set3(elem1, elem2, elem3) + else this + def elements: Iterator[A] = + Iterator(elem1, elem2, elem3, elem4) + override def foreach(f: A => Unit): Unit = { + f(elem1); f(elem2); f(elem3); f(elem4) + } + } +} diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala index 8c00df3f21..1c1cfbe929 100644 --- a/src/library/scala/collection/immutable/HashMap.scala +++ b/src/library/scala/collection/immutable/HashMap.scala @@ -11,48 +11,39 @@ package scala.collection.immutable -import Predef._ - -/** The canonical factory methods for <a href="HashMap.html">immutable HashMap's</a>. +import generic._ +import annotation.unchecked.uncheckedVariance + +/** This class implements immutable maps using a hash table. + * It is optimized for sequential accesses where the last updated table is accessed most often. + * It supports with reasonable efficiency accesses to previous versions of the table by keeping + * a change log that's regularly compacted. + * It needs to synchronize most methods, so it is less suitable for highly concurrent accesses. + * + * @note the builder of a hash map returns specialized representations EmptyMap,Map1,..., Map4 + * for maps of size <= 4. * * @author Martin Odersky * @version 2.0, 19/01/2007 */ -object HashMap { - - /** The empty map of this type */ - def empty[A, B] = new HashMap[A, B] - - /** The canonical factory for this type - */ - def apply[A, B](elems: (A, B)*) = empty[A, B] ++ elems -} - -/** This class implements immutable maps/sets using a hash table. - * It is optimized for sequential accesses where the last updated table is accessed most often. - * It supports with reasonable efficiency accesses to previous versions of the table by keeping - * a change log that's regularly compacted. - * It needs to synchronize most methods, so it is less suitable for highly concurrent accesses. - * - * @author Martin Odersky - * @version 2.0, 19/01/2007 - */ @serializable -class HashMap[A, B] extends Map[A,B] with mutable.HashTable[A] { - type Entry = mutable.DefaultEntry[A, Any] +class HashMap[A, +B] extends Map[A,B] with ImmutableMapTemplate[A, B, HashMap[A, B]] with mutable.HashTable[A] { + + type Entry = collection.mutable.DefaultEntry[A, Any] - protected var later: HashMap[A, B] = null + protected var later: HashMap[A, B @uncheckedVariance] = null protected var oldKey: A = _ - protected var oldValue: Option[B] = _ + protected var oldValue: Option[B @uncheckedVariance] = _ protected var deltaSize: Int = _ - def empty[C]: Map[A, C] = new EmptyMap[A, C] + override def empty = HashMap.empty[A, B] + override def mapBuilder[A, B]: Builder[(A, B), HashMap[A, B], Any] = HashMap.newBuilder[A, B] def get(key: A): Option[B] = synchronized { - var m = this + var m: HashMap[A, _ >: B] = this var cnt = 0 while (m.later != null) { - if (key == m.oldKey) return m.oldValue + if (key == m.oldKey) return m.oldValue.asInstanceOf[Option[B]] cnt += 1 m = m.later } @@ -62,7 +53,7 @@ class HashMap[A, B] extends Map[A,B] with mutable.HashTable[A] { else Some(getValue(e)) } - def update [B1 >: B](key: A, value: B1): Map[A, B1] = synchronized { + def add [B1 >: B] (key: A, value: B1): HashMap[A, B1] = synchronized { makeCopyIfUpdated() val e = findEntry(key) if (e == null) { @@ -72,22 +63,39 @@ class HashMap[A, B] extends Map[A,B] with mutable.HashTable[A] { markUpdated(key, Some(getValue(e)), 0) e.value = value } - later + later.asInstanceOf[HashMap[A, B1]] } - def - (key: A): Map[A, B] = synchronized { + /** Add a key/value pair to this map. + * @param kv the key/value pair + * @return A new map with the new binding added to this map + */ + override def + [B1 >: B] (kv: (A, B1)): HashMap[A, B1] = add(kv._1, kv._2) + + /** Adds two or more elements to this collection and returns + * either the collection itself (if it is mutable), or a new collection + * with the added elements. + * + * @param elem1 the first element to add. + * @param elem2 the second element to add. + * @param elems the remaining elements to add. + */ + override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): HashMap[A, B1] = + this + elem1 + elem2 ++ collection.Iterable.fromOld(elems) + + def - (key: A): HashMap[A, B] = synchronized { makeCopyIfUpdated() val e = findEntry(key) if (e == null) this else { markUpdated(key, Some(getValue(e)), -1) later removeEntry key - later + later.asInstanceOf[HashMap[A, B]] } } override def size: Int = synchronized { - var m = this + var m: HashMap[A, _ >: B] = this var cnt = 0 var s = 0 while (m.later != null) { @@ -110,7 +118,7 @@ class HashMap[A, B] extends Map[A,B] with mutable.HashTable[A] { private def logLimit: Int = Math.sqrt(table.length).toInt - private def markUpdated(key: A, ov: Option[B], delta: Int) { + private[this] def markUpdated(key: A, ov: Option[B], delta: Int) { val lv = loadFactor later = new HashMap[A, B] { override def initialSize = 0 @@ -124,8 +132,8 @@ class HashMap[A, B] extends Map[A,B] with mutable.HashTable[A] { deltaSize = delta } - private def makeCopy(last: HashMap[A, B]) { - def undo(m: HashMap[A, B]) { + private def makeCopy(last: HashMap[A, _ >: B]) { + def undo(m: HashMap[A, _ >: B]) { if (m ne last) { undo(m.later) if (m.deltaSize == 1) removeEntry(m.oldKey) @@ -143,7 +151,7 @@ class HashMap[A, B] extends Map[A,B] with mutable.HashTable[A] { } val ltable = last.table val s = ltable.length - table = new Array[mutable.HashEntry[A, Entry]](s) + table = new scala.Array[collection.mutable.HashEntry[A, Entry]](s) var i = 0 while (i < s) { table(i) = copy(ltable(i).asInstanceOf[Entry]) @@ -156,9 +164,20 @@ class HashMap[A, B] extends Map[A,B] with mutable.HashTable[A] { } private def makeCopyIfUpdated() { - var m = this + var m: HashMap[A, _ >: B] = this while (m.later != null) m = m.later if (m ne this) makeCopy(m) } } +/** A factory object for immutable HashMaps. + * + * @author Martin Odersky + * @version 2.8 + */ +object HashMap extends ImmutableMapFactory[HashMap] { + type Coll = HashMap[_, _] + implicit def builderFactory[A, B]: BuilderFactory[(A, B), HashMap[A, B], Coll] = new BuilderFactory[(A, B), HashMap[A, B], Coll] { def apply(from: Coll) = from.mapBuilder[A, B] } + def empty[A, B]: HashMap[A, B] = new HashMap +} + diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala index 11573e17ea..d5ee878c76 100644 --- a/src/library/scala/collection/immutable/HashSet.scala +++ b/src/library/scala/collection/immutable/HashSet.scala @@ -10,39 +10,30 @@ package scala.collection.immutable -/** The canonical factory methods for <a href="HashSet.html">immutable HashSet's<la>. - * - * @author Martin Odersky - * @version 2.0, 19/01/2007 - */ -object HashSet { - - /** The empty set of this type. - */ - def empty[A] = new HashSet[A] +import generic._ + +/** This class implements immutable sets using a hash table. + * It is optimized for sequential accesses where the last updated table is accessed most often. + * It supports with reasonable efficiency accesses to previous versions of the table by keeping + * a change log that's regularly compacted. + * It needs to synchronize most methods, so it is less suitable for highly concurrent accesses. + * + * @note the builder of a hash set returns specialized representations EmptySet,Set1,..., Set4 + * for sets of size <= 4. + * + * @author Martin Odersky + * @version 2.8 + */ +@serializable +class HashSet[A] extends Set[A] with SetTemplate[A, HashSet[A]] with mutable.FlatHashTable[A] { - /** The canonical factory for this type - */ - def apply[A](elems: A*) = empty[A] ++ elems -} + override def empty = HashSet.empty + override def traversibleBuilder[B]: Builder[B, HashSet[B], Any] = HashSet.newBuilder[B] -/** This class implements immutable maps/sets using a hash table. - * It is optimized for sequential accesses where the last updated table is accessed most often. - * It supports with reasonable efficiency accesses to previous versions of the table by keeping - * a change log that's regularly compacted. - * It needs to synchronize most methods, so it is less suitable for highly concurrent accesses. - * - * @author Martin Odersky - * @version 2.0, 19/01/2007 - */ -@serializable -class HashSet[A] extends Set[A] with mutable.FlatHashTable[A] { protected var later: HashSet[A] = null protected var changedElem: A = _ protected var deleted: Boolean = _ - def empty[C]: Set[C] = new EmptySet[C] - def contains(elem: A): Boolean = synchronized { var m = this var cnt = 0 @@ -55,7 +46,7 @@ class HashSet[A] extends Set[A] with mutable.FlatHashTable[A] { m.containsEntry(elem) } - def + (elem: A): Set[A] = synchronized { + def + (elem: A): HashSet[A] = synchronized { makeCopyIfUpdated() if (containsEntry(elem)) this else { @@ -65,7 +56,7 @@ class HashSet[A] extends Set[A] with mutable.FlatHashTable[A] { } } - def - (elem: A): Set[A] = synchronized { + def - (elem: A): HashSet[A] = synchronized { makeCopyIfUpdated() if (!containsEntry(elem)) this else { @@ -119,8 +110,8 @@ class HashSet[A] extends Set[A] with mutable.FlatHashTable[A] { else removeEntry(m.changedElem) } } - table = new Array[AnyRef](last.table.length) - Array.copy(last.table, 0, table, 0, table.length) + table = new scala.Array[AnyRef](last.table.length) + scala.Array.copy(last.table, 0, table, 0, table.length) tableSize = last.tableSize threshold = last.threshold undo(this) @@ -134,3 +125,14 @@ class HashSet[A] extends Set[A] with mutable.FlatHashTable[A] { } } +/** A factory object for immutable HashSets + * + * @author Martin Odersky + * @version 2.8 + */ +object HashSet extends SetFactory[HashSet] { + type Coll = HashSet[_] + implicit def builderFactory[A]: BuilderFactory[A, HashSet[A], Coll] = new BuilderFactory[A, HashSet[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def empty[A]: HashSet[A] = new HashSet +} + diff --git a/src/library/scala/collection/immutable/ImmutableIterator.scala b/src/library/scala/collection/immutable/ImmutableIterator.scala.disabled index 70d75e1dde..7733c17bec 100644 --- a/src/library/scala/collection/immutable/ImmutableIterator.scala +++ b/src/library/scala/collection/immutable/ImmutableIterator.scala.disabled @@ -8,6 +8,7 @@ // $Id$ +// Not clear whether this is needed. How is it different from a Stream? package scala.collection.immutable /** An object for creating immutable iterators. @@ -40,9 +41,9 @@ object ImmutableIterator { * by a lazy immutable iterator (right). */ def apply[A](left : ImmutableIterator[A], item : A, right : () => ImmutableIterator[A]) : ImmutableIterator[A] = left match { - case NonEmpty(first, middle) => + case NonEmpty(first, middle) => val rest = NonEmpty(item,right); - NonEmpty(first, apply(middle, () => rest)); + NonEmpty(first, apply(middle, () => rest)); case Empty => NonEmpty(item, right); } diff --git a/src/library/scala/collection/immutable/IntMap.scala b/src/library/scala/collection/immutable/IntMap.scala index c05f7ec1a8..69c68eb135 100644 --- a/src/library/scala/collection/immutable/IntMap.scala +++ b/src/library/scala/collection/immutable/IntMap.scala @@ -42,7 +42,7 @@ object IntMap{ def empty[T] : IntMap[T] = IntMap.Nil; def singleton[T](key : Int, value : T) : IntMap[T] = IntMap.Tip(key, value); def apply[T](elems : (Int, T)*) : IntMap[T] = - elems.foldLeft(empty[T])((x, y) => x.update(y._1, y._2)); + elems.foldLeft(empty[T])((x, y) => x.add(y._1, y._2)); private[immutable] case object Nil extends IntMap[Nothing]{ @@ -133,8 +133,8 @@ import IntMap._; * <a href="http://citeseer.ist.psu.edu/okasaki98fast.html">Fast Mergeable Integer Maps</a> * by Okasaki and Gill. Essentially a trie based on binary digits of the the integers. */ -sealed abstract class IntMap[+T] extends scala.collection.immutable.Map[Int, T]{ - def empty[S] : IntMap[S] = IntMap.Nil; +sealed abstract class IntMap[+T] extends scala.collection.immutable.Map[Int, T] with scala.collection.generic.ImmutableMapTemplate[Int, T, IntMap[T]] { + override def empty: IntMap[T] = IntMap.Nil; override def toList = { val buffer = new scala.collection.mutable.ListBuffer[(Int, T)]; @@ -209,13 +209,13 @@ sealed abstract class IntMap[+T] extends scala.collection.immutable.Map[Int, T]{ case IntMap.Nil => IntMap.Nil; } - override def transform[S](f : (Int, T) => S) : IntMap[S] = this match { + def transform[S](f : (Int, T) => S) : IntMap[S] = this match { case b@IntMap.Bin(prefix, mask, left, right) => b.bin(left.transform(f), right.transform(f)); case t@IntMap.Tip(key, value) => t.withValue(f(key, value)); case IntMap.Nil => IntMap.Nil; } - final def size : Int = this match { + final override def size : Int = this match { case IntMap.Nil => 0; case IntMap.Tip(_, _) => 1; case IntMap.Bin(_, _, left, right) => left.size + right.size; @@ -239,15 +239,18 @@ sealed abstract class IntMap[+T] extends scala.collection.immutable.Map[Int, T]{ case IntMap.Nil => error("key not found"); } - def update[S >: T](key : Int, value : S) : IntMap[S] = this match { + def add[S >: T](key : Int, value : S) : IntMap[S] = this match { case IntMap.Bin(prefix, mask, left, right) => if (!hasMatch(key, prefix, mask)) join(key, IntMap.Tip(key, value), prefix, this); - else if (zero(key, mask)) IntMap.Bin(prefix, mask, left.update(key, value), right) - else IntMap.Bin(prefix, mask, left, right.update(key, value)); + else if (zero(key, mask)) IntMap.Bin(prefix, mask, left.add(key, value), right) + else IntMap.Bin(prefix, mask, left, right.add(key, value)); case IntMap.Tip(key2, value2) => if (key == key2) IntMap.Tip(key, value); else join(key, IntMap.Tip(key, value), key2, this); case IntMap.Nil => IntMap.Tip(key, value); } + /** @deprecated use add instead */ + @deprecated override def update[S >: T](key: Int, value: S): IntMap[S] = add(key, value) + /** * Updates the map, using the provided function to resolve conflicts if the key is already present. * Equivalent to @@ -370,11 +373,8 @@ sealed abstract class IntMap[+T] extends scala.collection.immutable.Map[Int, T]{ */ def intersection[R](that : IntMap[R]) : IntMap[T] = this.intersectionWith(that, (key : Int, value : T, value2 : R) => value); - override def ++[S >: T](that : Iterable[(Int, S)]) = that match { - case (that : IntMap[_]) => this.unionWith[S](that.asInstanceOf[IntMap[S]], (key, x, y) => y); - case that => that.foldLeft(this : IntMap[S])({case (m, (x, y)) => m.update(x, y)}); - } - + def ++[S >: T](that : IntMap[S]) = + this.unionWith[S](that, (key, x, y) => y) /** * The entry with the lowest key value considered in unsigned order. @@ -382,7 +382,7 @@ sealed abstract class IntMap[+T] extends scala.collection.immutable.Map[Int, T]{ final def firstKey : Int = this match { case Bin(_, _, l, r) => l.firstKey; case Tip(k, v) => k; - case Nil => error("Empty set") + case IntMap.Nil => error("Empty set") } /** @@ -391,7 +391,6 @@ sealed abstract class IntMap[+T] extends scala.collection.immutable.Map[Int, T]{ final def lastKey : Int = this match { case Bin(_, _, l, r) => r.lastKey; case Tip(k, v) => k; - case Nil => error("Empty set") + case IntMap.Nil => error("Empty set") } } - diff --git a/src/library/scala/collection/immutable/Iterable.scala b/src/library/scala/collection/immutable/Iterable.scala new file mode 100755 index 0000000000..602ee1fffb --- /dev/null +++ b/src/library/scala/collection/immutable/Iterable.scala @@ -0,0 +1,23 @@ +package scala.collection.immutable + +import generic._ + +/** A subtrait of collection.Iterable which represents iterables + * that cannot be mutated. + * + * @author Matthias Zenger + * @autor Martin Odersky + * @version 2.8 + */ +trait Iterable[+A] extends Traversible[A] with collection.Iterable[A] with IterableTemplate[A, Iterable[A]] { self => + override protected[this] def newBuilder = Iterable.newBuilder + override def traversibleBuilder[B]: Builder[B, Iterable[B], Any] = Iterable.newBuilder[B] +} + +/* A factory object for the trait `Iterable` */ +object Iterable extends TraversibleFactory[Iterable] { + type Coll = Iterable[_] + implicit def builderFactory[A]: BuilderFactory[A, Iterable[A], Coll] = new BuilderFactory[A, Iterable[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Iterable[A], Any] = new mutable.ListBuffer +} + diff --git a/src/library/scala/collection/immutable/LinearSequence.scala b/src/library/scala/collection/immutable/LinearSequence.scala new file mode 100755 index 0000000000..0508ecca29 --- /dev/null +++ b/src/library/scala/collection/immutable/LinearSequence.scala @@ -0,0 +1,17 @@ +package scala.collection.immutable + +import generic._ + +/** A subtrait of collection.Sequence which represents sequences + * that cannot be mutated. + */ +trait LinearSequence[+A] extends Sequence[A] with collection.LinearSequence[A] with LinearSequenceTemplate[A, LinearSequence[A]] { + override protected[this] def newBuilder = LinearSequence.newBuilder + override def traversibleBuilder[B]: Builder[B, LinearSequence[B], Any] = LinearSequence.newBuilder[B] +} + +object LinearSequence extends SequenceFactory[LinearSequence] { + type Coll = LinearSequence[_] + implicit def builderFactory[A]: BuilderFactory[A, LinearSequence[A], Coll] = new BuilderFactory[A, LinearSequence[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, LinearSequence[A], Any] = new mutable.ListBuffer +} diff --git a/src/library/scalax/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index cb5965a18a..4670539917 100644..100755 --- a/src/library/scalax/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -9,11 +9,10 @@ // $Id: List.scala 16287 2008-10-18 13:41:36Z nielsen $ -package scalax.collection.immutable +package scala.collection.immutable import mutable.ListBuffer -import generic.{SequenceTemplate, SequenceFactory, EmptyIterableFactory, Builder} -import annotation.unchecked.uncheckedVariance +import generic.{SequenceFactory, Builder, BuilderFactory, LinearSequenceTemplate} /** A class representing an ordered collection of elements of type * <code>a</code>. This class comes with two implementing case @@ -24,11 +23,9 @@ import annotation.unchecked.uncheckedVariance * @author Martin Odersky and others * @version 2.8 */ -sealed abstract class List[+A] extends Stream[A] - with SequenceTemplate[List, A @uncheckedVariance] - with Product { +sealed abstract class List[+A] extends LinearSequence[A] with Product with LinearSequenceTemplate[A, List[A]] { - import collection.{Iterable, OrderedIterable, Sequence, Vector} + import collection.{Iterable, Traversible, Sequence, Vector} /** Returns true if the list does not contain any elements. * @return <code>true</code>, iff the list is empty. @@ -50,7 +47,8 @@ sealed abstract class List[+A] extends Stream[A] def tail: List[A] /** Creates a list buffer as builder for this class */ - override def newBuilder[B]: Builder[List, B] = new ListBuffer[B] + override protected[this] def newBuilder = List.newBuilder + override def traversibleBuilder[B]: Builder[B, List[B], Any] = List.newBuilder[B] // New methods in List @@ -63,7 +61,7 @@ sealed abstract class List[+A] extends Stream[A] * @ex <code>1 :: List(2, 3) = List(2, 3).::(1) = List(1, 2, 3)</code> */ def ::[B >: A] (x: B): List[B] = - new scalax.collection.immutable.::(x, this) + new scala.collection.immutable.::(x, this) /** <p> * Returns a list resulting from the concatenation of the given @@ -99,7 +97,7 @@ sealed abstract class List[+A] extends Stream[A] /** Apply a function to all the elements of the list, and return the * reversed list of results. This is equivalent to a call to <code>map</code> * followed by a call to <code>reverse</code>, but more efficient. - * !!! should we deprecate this? Why have reverseMap, but not filterMap, say? + * !!! should we deprecate this? Why have reverseMap, but not filterMap or reverseFilter, say? * @param f the function to apply to each elements. * @return the reversed list of results. */ @@ -112,8 +110,8 @@ sealed abstract class List[+A] extends Stream[A] } /** Like xs map f, but returns <code>xs</code> unchanged if function - * <code>f</code> maps all elements to themselves (wrt eq) - * @note Unlike `map`, `mapConserve` is not tail-recursive + * <code>f</code> maps all elements to themselves (wrt ==). + * @note Unlike `map`, `mapConserve` is not tail-recursive. */ def mapConserve[B >: A] (f: A => B): List[B] = { def loop(ys: List[A]): List[B] = @@ -121,7 +119,7 @@ sealed abstract class List[+A] extends Stream[A] else { val head0 = ys.head val head1 = f(head0) - if (head1.asInstanceOf[AnyRef] eq head0.asInstanceOf[AnyRef]) { + if (head1 == head0) { loop(ys.tail) } else { val ys1 = head1 :: ys.tail.mapConserve(f) @@ -142,10 +140,20 @@ sealed abstract class List[+A] extends Stream[A] // Overridden methods from IterableTemplate or overloaded variants of such methods - /** Appends two list objects. + /** Create a new list which contains all elements of this list + * followed by all elements of Traversible `that' */ - override def ++[B >: A](that: Iterable[B]): List[B] = - this ::: that.toList + override def ++[B >: A, That](that: Traversible[B])(implicit bf: BuilderFactory[B, That, List[A]]): That = { + val b = bf(this) + if (b.isInstanceOf[ListBuffer[_]]) (this ::: that.toList).asInstanceOf[That] + else super.++(that) + } + + /** Create a new list which contains all elements of this list + * followed by all elements of Iterator `that' + */ + override def ++[B >: A, That](that: Iterator[B])(implicit bf: BuilderFactory[B, That, List[A]]): That = + this ++ that.toList /** Overrides the method in Iterable for efficiency. * @@ -195,9 +203,9 @@ sealed abstract class List[+A] extends Stream[A] * @return the list with elements belonging to the given index range. */ override def slice(start: Int, end: Int): List[A] = { - val s = start max 0 - val e = end min this.length - drop(s) take (e - s) + var len = end + if (start > 0) len -= start + drop(start) take len } /** Returns the rightmost <code>n</code> elements from this list. @@ -279,128 +287,25 @@ sealed abstract class List[+A] extends Stream[A] (b.toList, these) } - /** Returns the list resulting from applying the given function <code>f</code> to each - * element of this list. - * - * @param f function to apply to each element. - * @return <code>[f(a0), ..., f(an)]</code> if this list is <code>[a0, ..., an]</code>. - */ - final override def map[B](f: A => B): List[B] = { - val b = new ListBuffer[B] - var these = this - while (!these.isEmpty) { - b += f(these.head) - these = these.tail - } - b.toList - } - - /** Returns all the elements of this list that satisfy the - * predicate <code>p</code>. The order of the elements is preserved. - * It is guarenteed that the receiver list itself is returned iff all its - * elements satisfy the predicate `p'. Hence the following equality is valid: - * - * (xs filter p) eq xs == xs forall p - * - * @param p the predicate used to filter the list. - * @return the elements of this list satisfying <code>p</code>. + /** A list consisting of all elements of this list in reverse order. */ - final override def filter(p: A => Boolean): List[A] = { - // return same list if all elements satisfy p + override def reverse: List[A] = { + var result: List[A] = Nil var these = this - var allTrue = true - val b = new ListBuffer[A] while (!these.isEmpty) { - if (p(these.head)) b += these.head - else allTrue = false + result = these.head :: result these = these.tail } - if (allTrue) this else b.toList - } - - /** Applies the given function <code>f</code> to each element of - * this list, then concatenates the results. - * - * @param f the function to apply on each element. - * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if - * this list is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>. - */ - final override def flatMap[B](f: A => Iterable[B]): List[B] = { - val b = new ListBuffer[B] - var these = this - while (!these.isEmpty) { - b ++= f(these.head) - these = these.tail - } - b.toList - } - - /** Returns a list formed from this list and the specified list - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * If one of the two lists is longer than the other, its remaining elements are ignored. - * - * !!! todo: perform speed with inherited version from Iterable, and drop - * if not significantly better - * @return <code>List((a<sub>0</sub>,b<sub>0</sub>), ..., - * (a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>))</code> when - * <code>List(a<sub>0</sub>, ..., a<sub>m</sub>) - * zip List(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked. - */ - def zip[B](that: List[B]): List[(A, B)] = { - val b = new ListBuffer[(A, B)] - var these = this - var those = that - while (!these.isEmpty && !those.isEmpty) { - b += ((these.head, those.head)) - these = these.tail - those = those.tail - } - b.toList - } - - /** Returns a list formed from this list and the specified list - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * - * @param that list <code>that</code> may have a different length - * as the self list. - * @param thisElem element <code>thisElem</code> is used to fill up the - * resulting list if the self list is shorter than - * <code>that</code> - * @param thatElem element <code>thatElem</code> is used to fill up the - * resulting list if <code>that</code> is shorter than - * the self list - * @return <code>List((a<sub>0</sub>,b<sub>0</sub>), ..., - * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>), - * ..., {elem,b<sub>m</sub>})</code> - * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip - * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is - * invoked where <code>m > n</code>. - */ - def zipAll[B, C >: A, D >: B](that: List[B], thisElem: C, thatElem: D): List[(C, D)] = { - val b = new ListBuffer[(C, D)] - var these = this - var those = that - while (!these.isEmpty && !those.isEmpty) { - b += ((these.head, those.head)) - these = these.tail - those = those.tail - } - while (!these.isEmpty) { - b += ((these.head, thatElem)) - these = these.tail - } - while (!those.isEmpty) { - b += ((thisElem, those.head)) - those = those.tail - } - b.toList + result } override def stringPrefix = "List" - override def toStream : Stream[A] = this + override def toStream : Stream[A] = + if (isEmpty) Stream.Empty + else new Stream.Cons(head, tail.toStream) + + // !!! todo: work in patch /** Computes the difference between this list and the given list * <code>that</code>. @@ -424,7 +329,7 @@ sealed abstract class List[+A] extends Stream[A] * <code>x</code>. * * @param x the object to remove from this list. - * @return this list without the elements of the given object + * @return this list without occurrences of the given object * <code>x</code>. * @deprecated use diff instead */ @@ -532,6 +437,10 @@ case object Nil extends List[Nothing] { throw new NoSuchElementException("head of empty list") override def tail: List[Nothing] = throw new NoSuchElementException("tail of empty list") + override def equals(that: Any) = that match { + case that1: Sequence[_] => that1.isEmpty + case _ => false + } } /** A non empty list characterized by a head and a tail. @@ -540,7 +449,7 @@ case object Nil extends List[Nothing] { * @version 1.0, 15/07/2003 */ @SerialVersionUID(0L - 8476791151983527571L) -final case class ::[B](private var hd: B, private[scalax] var tl: List[B]) extends List[B] { +final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B] { override def head : B = hd override def tail : List[B] = tl override def isEmpty: Boolean = false @@ -572,16 +481,20 @@ final case class ::[B](private var hd: B, private[scalax] var tl: List[B]) exten /** This object provides methods for creating specialized lists, and for * transforming special kinds of lists (e.g. lists of lists). * - * @author Martin Odersky and others - * @version 1.0, 15/07/2003 + * @author Martin Odersky + * @version 2.8 */ -object List extends SequenceFactory[List] with EmptyIterableFactory[List] { +object List extends SequenceFactory[List] { + + import collection.{Iterable, Sequence, Vector} - override val empty: List[Nothing] = Nil + type Coll = List[_] + implicit def builderFactory[A]: BuilderFactory[A, List[A], Coll] = new BuilderFactory[A, List[A], Coll] { def apply(from: Coll) = new ListBuffer[A] } + def newBuilder[A]: Builder[A, List[A], Any] = new ListBuffer[A] - override def apply[A](xs: A*) = xs.asInstanceOf[Iterable[A]].toList // !@! + override def empty[A]: List[A] = Nil - override def newBuilder[B]: Builder[List, B] = new ListBuffer[B] + override def apply[A](xs: A*): List[A] = Iterable.fromOld(xs).toList /** Create a sorted list with element values * <code>v<sub>n+1</sub> = step(v<sub>n</sub>)</code> @@ -772,7 +685,7 @@ object List extends SequenceFactory[List] with EmptyIterableFactory[List] { * @deprecated use <code>str.toList</code> instead */ @deprecated def fromString(str: String): List[Char] = - str.toList.asInstanceOf[List[Char]] // !@! + Iterable.fromOld(str).toList /** Returns the given list of characters as a string. * @@ -948,5 +861,5 @@ object List extends SequenceFactory[List] with EmptyIterableFactory[List] { /** Only used for list serialization */ @SerialVersionUID(0L - 8476791151975527571L) -private[scalax] case object ListSerializeEnd +private[scala] case object ListSerializeEnd diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala index ba31ab906a..67fb8f2a25 100644 --- a/src/library/scala/collection/immutable/ListMap.scala +++ b/src/library/scala/collection/immutable/ListMap.scala @@ -12,21 +12,14 @@ package scala.collection.immutable -/** The canonical factory of <a href="ListMap.html">ListMap</a>'s */ -object ListMap { - - /** The empty map of this type - * @deprecated use <code>empty</code> instead - */ - @deprecated - def Empty[A, B] = new ListMap[A, B] +import generic._ - /** The empty map of this type */ - def empty[A, B] = new ListMap[A, B] +/** The canonical factory of <a href="ListMap.html">ListMap</a>'s */ +object ListMap extends ImmutableMapFactory[ListMap] { - /** The canonical factory for this type - */ - def apply[A, B](elems: (A, B)*) = empty[A, B] ++ elems + type Coll = ListMap[_,_] + implicit def builderFactory[A, B]: BuilderFactory[(A, B), ListMap[A, B], Coll] = new BuilderFactory[(A, B), ListMap[A, B], Coll] { def apply(from: Coll) = from.mapBuilder[A, B] } + def empty[A, B]: ListMap[A, B] = new ListMap } /** This class implements immutable maps using a list-based data @@ -39,18 +32,16 @@ object ListMap { * @version 2.0, 01/01/2007 */ @serializable -class ListMap[A, +B] extends Map[A, B] { +class ListMap[A, +B] extends Map[A, B] with ImmutableMapTemplate[A, B, ListMap[A, B]] { - /** Returns a <code>new ListMap</code> instance mapping keys of the - * same type to values of type <code>C</code>. - */ - def empty[C] = ListMap.empty[A, C] + override def empty = ListMap.empty + override def mapBuilder[A, B]: Builder[(A, B), ListMap[A, B], Any] = ListMap.newBuilder[A, B] /** Returns the number of mappings in this map. * * @return number of mappings in this map. */ - def size: Int = 0 + override def size: Int = 0 /** Checks if this map maps <code>key</code> to a value and return the * value if it exists. @@ -69,7 +60,24 @@ class ListMap[A, +B] extends Map[A, B] { * @param key the key element of the updated entry. * @param value the value element of the updated entry. */ - def update [B1 >: B](key: A, value: B1): ListMap[A, B1] = new Node(key, value) + def add [B1 >: B] (key: A, value: B1): ListMap[A, B1] = new Node[B1](key, value) + + /** Add a key/value pair to this map. + * @param kv the key/value pair + * @return A new map with the new binding added to this map + */ + override def + [B1 >: B] (kv: (A, B1)): ListMap[A, B1] = add(kv._1, kv._2) + + /** Adds two or more elements to this collection and returns + * either the collection itself (if it is mutable), or a new collection + * with the added elements. + * + * @param elem1 the first element to add. + * @param elem2 the second element to add. + * @param elems the remaining elements to add. + */ + override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): ListMap[A, B1] = + this + elem1 + elem2 ++ collection.Iterable.fromOld(elems) /** This creates a new mapping without the given <code>key</code>. * If the map does not contain a mapping for the given key, the @@ -136,9 +144,9 @@ class ListMap[A, +B] extends Map[A, B] { * @param k ... * @param v ... */ - override def update [B2 >: B1](k: A, v: B2): ListMap[A, B2] = { + override def add [B2 >: B1](k: A, v: B2): ListMap[A, B2] = { val m = if (contains(k)) this - k else this - new m.Node(k, v) + new m.Node[B2](k, v) } /** Creates a new mapping without the given <code>key</code>. @@ -157,6 +165,6 @@ class ListMap[A, +B] extends Map[A, B] { else new tail.Node(key, value) } - override protected def next: ListMap[A,B1] = ListMap.this + override protected def next: ListMap[A, B1] = ListMap.this } } diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala index 35ead05b63..bf56a76f72 100644 --- a/src/library/scala/collection/immutable/ListSet.scala +++ b/src/library/scala/collection/immutable/ListSet.scala @@ -11,25 +11,13 @@ package scala.collection.immutable - -//import Predef.NoSuchElementException +import generic._ /** The canonical factory of <a href="ListSet.html">ListSet</a>'s */ -object ListSet { - - /** constructs an empty ListSet - * @deprecated use <code>empty</code> instead - */ - @deprecated - def Empty[A] = new ListSet[A] - - /** The empty set of this type. - */ +object ListSet extends SetFactory[ListSet] { + type Coll = ListSet[_] + implicit def builderFactory[A]: BuilderFactory[A, ListSet[A], Coll] = new BuilderFactory[A, ListSet[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } def empty[A] = new ListSet[A] - - /** The canonical factory for this type - */ - def apply[A, B](elems: A*) = empty[A] ++ elems } @@ -42,17 +30,18 @@ object ListSet { * @version 1.0, 09/07/2003 */ @serializable -class ListSet[A] extends AnyRef with Set[A] { +class ListSet[A] extends Set[A] with SetTemplate[A, ListSet[A]] { self => /** Returns the number of elements in this set. * * @return number of set elements. */ - def size: Int = 0 + override def size: Int = 0 override def isEmpty: Boolean = true; - def empty[B] = ListSet.empty[B] + override def empty = ListSet.empty + override def traversibleBuilder[B]: Builder[B, ListSet[B], Any] = ListSet.newBuilder[B] /** Checks if this set contains element <code>elem</code>. * @@ -76,24 +65,13 @@ class ListSet[A] extends AnyRef with Set[A] { * @return the new iterator */ def elements: Iterator[A] = new Iterator[A] { - var that: ListSet[A] = ListSet.this; + var that: ListSet[A] = self; def hasNext = !that.isEmpty; def next: A = if (!hasNext) throw new NoSuchElementException("next on empty iterator") else { val res = that.elem; that = that.next; res } } - /** Compares two sets for equality. - * Two set are equal iff they contain the same elements. - */ - override def equals(obj: Any): Boolean = obj match { - case _: scala.collection.Set[_] => - val that = obj.asInstanceOf[scala.collection.Set[A]] - (size == that.size) && (toList forall that.contains) - case _ => - false - } - /** * @throws Predef.NoSuchElementException */ @@ -106,11 +84,12 @@ class ListSet[A] extends AnyRef with Set[A] { @serializable protected class Node(override protected val elem: A) extends ListSet[A] { + /** Returns the number of elements in this set. * * @return number of set elements. */ - override def size = ListSet.this.size + 1 + override def size = self.size + 1 /** Checks if this set is empty. * @@ -123,7 +102,7 @@ class ListSet[A] extends AnyRef with Set[A] { * @param elem the element to check for membership. * @return true, iff <code>elem</code> is contained in this set. */ - override def contains(e: A) = (e == elem) || ListSet.this.contains(e) + override def contains(e: A) = (e == elem) || self.contains(e) /** This method creates a new set with an additional element. */ @@ -132,11 +111,11 @@ class ListSet[A] extends AnyRef with Set[A] { /** <code>-</code> can be used to remove a single element from * a set. */ - override def -(e: A): ListSet[A] = if (e == elem) ListSet.this else { - val tail = ListSet.this - e; new tail.Node(elem) + override def -(e: A): ListSet[A] = if (e == elem) self else { + val tail = self - e; new tail.Node(elem) } - override protected def next: ListSet[A] = ListSet.this + override protected def next: ListSet[A] = self override def stringPrefix = "Set" } diff --git a/src/library/scala/collection/immutable/LongMap.scala b/src/library/scala/collection/immutable/LongMap.scala index 298d7c4e82..043fe2e882 100644 --- a/src/library/scala/collection/immutable/LongMap.scala +++ b/src/library/scala/collection/immutable/LongMap.scala @@ -43,7 +43,7 @@ object LongMap{ def empty[T] : LongMap[T] = LongMap.Nil; def singleton[T](key : Long, value : T) : LongMap[T] = LongMap.Tip(key, value); def apply[T](elems : (Long, T)*) : LongMap[T] = - elems.foldLeft(empty[T])((x, y) => x.update(y._1, y._2)); + elems.foldLeft(empty[T])((x, y) => x.add(y._1, y._2)); private[immutable] case object Nil extends LongMap[Nothing]{ @@ -134,8 +134,8 @@ import LongMap._; * <a href="http://citeseer.ist.psu.edu/okasaki98fast.html">Fast Mergeable Long Maps</a> * by Okasaki and Gill. Essentially a trie based on binary digits of the the integers. */ -sealed abstract class LongMap[+T] extends scala.collection.immutable.Map[Long, T]{ - def empty[S] : LongMap[S] = LongMap.Nil; +sealed abstract class LongMap[+T] extends scala.collection.immutable.Map[Long, T] with scala.collection.generic.ImmutableMapTemplate[Long, T, LongMap[T]] { + override def empty: LongMap[T] = LongMap.Nil; override def toList = { val buffer = new scala.collection.mutable.ListBuffer[(Long, T)]; @@ -210,13 +210,13 @@ sealed abstract class LongMap[+T] extends scala.collection.immutable.Map[Long, T case LongMap.Nil => LongMap.Nil; } - override def transform[S](f : (Long, T) => S) : LongMap[S] = this match { + def transform[S](f : (Long, T) => S) : LongMap[S] = this match { case b@LongMap.Bin(prefix, mask, left, right) => b.bin(left.transform(f), right.transform(f)); case t@LongMap.Tip(key, value) => t.withValue(f(key, value)); case LongMap.Nil => LongMap.Nil; } - final def size : Int = this match { + final override def size : Int = this match { case LongMap.Nil => 0; case LongMap.Tip(_, _) => 1; case LongMap.Bin(_, _, left, right) => left.size + right.size; @@ -240,7 +240,7 @@ sealed abstract class LongMap[+T] extends scala.collection.immutable.Map[Long, T case LongMap.Nil => error("key not found"); } - def update[S >: T](key : Long, value : S) : LongMap[S] = this match { + def add[S >: T](key : Long, value : S) : LongMap[S] = this match { case LongMap.Bin(prefix, mask, left, right) => if (!hasMatch(key, prefix, mask)) join(key, LongMap.Tip(key, value), prefix, this); else if (zero(key, mask)) LongMap.Bin(prefix, mask, left.update(key, value), right) else LongMap.Bin(prefix, mask, left, right.update(key, value)); @@ -249,6 +249,9 @@ sealed abstract class LongMap[+T] extends scala.collection.immutable.Map[Long, T case LongMap.Nil => LongMap.Tip(key, value); } + /** @deprecated use add instead */ + @deprecated override def update[S >: T](key: Long, value: S): LongMap[S] = add(key, value) + /** * Updates the map, using the provided function to resolve conflicts if the key is already present. * Equivalent to @@ -371,9 +374,7 @@ sealed abstract class LongMap[+T] extends scala.collection.immutable.Map[Long, T */ def intersection[R](that : LongMap[R]) : LongMap[T] = this.intersectionWith(that, (key : Long, value : T, value2 : R) => value); - override def ++[S >: T](that : Iterable[(Long, S)]) = that match { - case (that : LongMap[_]) => this.unionWith[S](that.asInstanceOf[LongMap[S]], (key, x, y) => y); - case that => that.foldLeft(this : LongMap[S])({case (m, (x, y)) => m.update(x, y)}); - } + def ++[S >: T](that : LongMap[S]) = + this.unionWith[S](that, (key, x, y) => y) } diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala index 0fa41a7f3b..442a325637 100644 --- a/src/library/scala/collection/immutable/Map.scala +++ b/src/library/scala/collection/immutable/Map.scala @@ -11,241 +11,66 @@ package scala.collection.immutable -import Predef._ +import generic._ -/** <p>An object for creating immutable maps. These are implemented using - * <a href="HashMap.html">immutable hash maps</a>. - * </p>*/ -object Map { - def empty[A, B]: Map[A, B] = new EmptyMap[A, B] +trait Map[A, +B] extends Iterable[(A, B)] + with collection.Map[A, B] + with ImmutableMapTemplate[A, B, Map[A, B]] { self => - def apply[A, B](elems: (A, B)*) = empty[A, B] ++ elems -} - -/** <p> - * This class defines the interface for immutable maps. Operations - * on an immutable map leave the original map unchanged, and return - * a new map if needed. - * </p> - * <p> - * Concrete map implementations have to provide functionality for - * the abstract methods in <a href="../Map.html" target="contentFrame"> - * <code>scala.collection.Map</code></a> as well as for - * <code>factory</code>, <code>update</code>, and <code>-</code>. - * </p> - * - * @author Matthias Zenger - * @author Erik Stenman - * @author Martin Odersky - * @version 1.2, 31/06/2006 - */ -trait Map[A, +B] extends collection.Map[A, B] { - - /** This method returns a new map instance of the same class - * mapping keys of the same type to values of type <code>C</code>. - */ - def empty[C]: Map[A, C] - - /** This method allows one to create a new map with an - * additional mapping from <code>key</code> - * to <code>value</code>. If the map contains already a - * mapping for <code>key</code>, it will be overridden by this - * function. - * - * @param key ... - * @param value ... - * @return the created map - * @deprecated use <code>+({A, B})</code> instead - */ - def update [B1 >: B] (key: A, value: B1): Map[A, B1] + override def empty: Map[A, B] = Map.empty + override def mapBuilder[A, B]: Builder[(A, B), Map[A, B], Any] = Map.newBuilder[A, B] /** Add a key/value pair to this map. - * @param kv the key/value pair. + * @param key the key + * @param value the value * @return A new map with the new binding added to this map */ - def + [B1 >: B] (kv: (A, B1)): Map[A, B1] = update(kv._1, kv._2) + def add [B1 >: B](key: A, value: B1): Map[A, B1] - /** Add two or more key/value pairs to this map. - * @param kv1 the first key/value pair. - * @param kv2 the second key/value pair. - * @param kvs the remaining key/value pairs. - * @return A new map with the new bindings added + /** Add a key/value pair to this map. + * @param kv the key/value pair + * @return A new map with the new binding added to this map */ - def + [B1 >: B] (kv1: (A, B1), kv2: (A, B1), kvs: (A, B1)*): Map[A, B1] = - this + kv1 + kv2 ++ kvs + override def + [B1 >: B] (kv: (A, B1)): Map[A, B1] = add(kv._1, kv._2) - /** Add a sequence of key/value pairs to this map. - * @param kvs the iterable object containing all key/value pairs. - * @return A new map with the new bindings added + /** Adds two or more elements to this collection and returns + * either the collection itself (if it is mutable), or a new collection + * with the added elements. + * + * @param elem1 the first element to add. + * @param elem2 the second element to add. + * @param elems the remaining elements to add. */ - def ++ [B1 >: B] (kvs: Iterable[(A, B1)]): Map[A, B1] = - ((this: Map[A, B1]) /: kvs) ((m, kv) => m + kv) + override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): Map[A, B1] = + this + elem1 + elem2 ++ collection.Iterable.fromOld(elems) - /** Add a sequence of key/value pairs to this map. - * @param kvs the iterator containing all key/value pairs. - * @return A new map with the new bindings added - */ - def ++ [B1 >: B] (kvs: Iterator[(A, B1)]): Map[A, B1] = - ((this: Map[A, B1]) /: kvs) ((m, kv) => m + kv) - - /** Remove a key from this map - * @param key the key to be removed - * @return If the map does not contain a binding for <code>key</code> - * it is returned unchanged. Otherwise, return a new map - * without a binding for <code>key</code> - */ - def - (key: A): Map[A, B] - - /** Remove two or more keys from this map - * @param key1 the first key to be removed - * @param key2 the second key to be removed - * @param keys the remaining keys to be removed - * @return A map without bindings for <code>keys</code> - * If the map is mutable, the bindings are removed in place - * and the map itself is returned. - * If the map is immutable, a new map with the bindings removed is returned. + /** A hash method compatible with <code>equals</code> */ - def - (key1: A, key2: A, keys: A*): Map[A, B] = - this - key1 - key2 -- keys - - /** Remove a sequence of keys from this map - * @param keys the keys to be removed - * @return A map without bindings for the given keys. - * If the map is mutable, the bindings are removed in place - * and the map itself is returned. - * If the map is immutable, a new map with the bindings removed is returned. - */ - def -- (keys: Iterable[A]): Map[A, B] = this -- keys.elements - - /** Remove a sequence of keys from this map - * @param keys the keys to be removed - * @return A map without bindings for the given keys. - * If the map is mutable, the bindings are removed in place - * and the map itself is returned. - * If the map is immutable, a new map with the bindings removed is returned. - */ - def -- (keys: Iterator[A]): Map[A, B] = - (this /: keys) ((m, key) => m - key) - + override def hashCode() = + (Map.hashSeed /: this) (_ * 41 + _.hashCode) /** The same map with a given default function */ - def withDefault[B1 >: B](d: A => B1): Map[A, B1] = new Map[A, B1] { - def size = Map.this.size - def get(key: A) = Map.this.get(key) - def elements = Map.this.elements - def empty[C] = Map.this.empty - def update [B2 >: B1](key: A, value: B2): Map[A, B2] = - Map.this.update(key, value) withDefault d - def -(key: A): Map[A, B1] = Map.this - key withDefault d - override def default(key: A): B1 = d(key) - } + def withDefault[B1 >: B](d: A => B1): Map[A, B1] = new Map.WithDefault[A, B1](this, d) /** The same map with a given default value */ - def withDefaultValue[B1 >: B](d: B1): Map[A, B1] = withDefault(x => d) - - /** This function transforms all the values of mappings contained - * in this map with function <code>f</code>. - * - * @param f A function over keys and values - * @return the updated map - */ - def transform[C](f: (A, B) => C): Map[A, C] = { - var res = empty[C] - foreach { case (key, value) => res = res.update(key, f(key, value)) } - res - } - - /** This method removes all the mappings for which the predicate - * <code>p</code> returns <code>false</code>. - * - * @param p A prediacte over key-value pairs - * @return the updated map - */ - override def filter(p: ((A, B)) => Boolean): Map[A, B] = { - var res = this - foreach { - case kv @ (key, _) => if (!p(kv)) { res = res - key } - } - res - } - - /** <p> - * This method defines syntactic sugar for adding a - * mapping. It is typically used in the following way: - * </p> - * <pre> - * map + key -> value - * </pre> - * @deprecated use <code>+({A, B})</code> instead - */ - @deprecated def +(key: A): MapTo = new MapTo(key) - - /** <code>incl</code> can be used to add many mappings at the same time - * to the map. The method assumes that a mapping is represented - * by a <code>Pair</code> object who's first component denotes the - * key, and who's second component refers to the value. - * - * @param mappings ... - * @return ... - * @deprecated use <code>+</code> instead - */ - @deprecated def incl[B1 >: B](mappings: (A, B1)*): Map[A, B1] = incl(mappings) - - /** <code>incl</code> can be used to add many mappings at the same time - * to the map. The method assumes that each mapping is represented - * by an Iterator over <code>Pair</code> objects who's first component - * denotes the key, and who's second component refers to the value. - * - * @deprecated use <code>++</code> instead - */ - @deprecated def incl[B1 >: B](map: Iterable[(A, B1)]): Map[A, B1] = { - val iter = map.elements - var res: Map[A, B1] = this - while (iter.hasNext) { - val (key, value) = iter.next - res = res.update(key, value) - } - res - } - - /** This method will return a map where all the mappings - * for the given sequence of keys are removed from the map. - * - * @param keys ... - * @return the updated map - * @deprecated use <code>-</code> instead - */ - @deprecated def excl(keys: A*): Map[A, B] = excl(keys) - - /** This method removes all the mappings for keys provided by an - * iterator over the elements of the <code>keys</code> object. - * - * @param keys ... - * @return the updated map - * @deprecated use <code>--</code> instead - */ - @deprecated def excl(keys: Iterable[A]): Map[A, B] = { - val iter = keys.elements - var res = this - while (iter.hasNext) { - res = res - iter.next - } - res - } - - /** This method controls how a mapping is represented in the string - * representation provided by method <code>toString</code>. - * - * @param p ... - * @return the string representation of a map entry - */ - @deprecated def mappingToString[B1 >: B](p: (A, B1)) = - p._1.toString() + " -> " + p._2 + def withDefaultValue[B1 >: B](d: B1): Map[A, B1] = new Map.WithDefault[A, B1](this, x => d) +} - /** @deprecated use <code>+({A, B})</code> instead - */ - @deprecated class MapTo(key: A) { - def -> [B1 >: B](value: B1) = update(key, value) +object Map extends ImmutableMapFactory[Map] { + private val hashSeed = "Map".hashCode + type Coll = Map[_, _] + implicit def builderFactory[A, B]: BuilderFactory[(A, B), Map[A, B], Coll] = new BuilderFactory[(A, B), Map[A, B], Coll] { def apply(from: Coll) = from.mapBuilder[A, B] } + + def empty[A, B]: Map[A, B] = FlexMap.empty + + class WithDefault[A, +B](underlying: Map[A, B], d: A => B) extends Map[A, B] { + override def size = underlying.size + def get(key: A) = underlying.get(key) + def elements = underlying.elements + override def empty = new WithDefault(underlying.empty, d) + def add[B1 >: B](key: A, value: B1): WithDefault[A, B1] = new WithDefault[A, B1](underlying.add[B1](key, value), d) + def - (key: A): WithDefault[A, B] = new WithDefault(underlying - key, d) + override def default(key: A): B = d(key) } } diff --git a/src/library/scala/collection/immutable/Map1.scala b/src/library/scala/collection/immutable/Map1.scala deleted file mode 100644 index 7fc1144da3..0000000000 --- a/src/library/scala/collection/immutable/Map1.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - - -package scala.collection.immutable - -import Predef.Pair - -/** This class implements immutable maps with exactly one entry - * - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Map1[A, +B](key1: A, value1: B) extends Map[A, B] { - - def size = 1 - - def get(key: A): Option[B] = - if (key == key1) Some(value1) else None - - def elements = Iterator.single((key1, value1)) - - def empty[B]: Map[A, B] = new EmptyMap[A, B] - - def update [B1 >: B](key: A, value: B1): Map[A, B1] = - if (key == key1) new Map1(key1, value) - else new Map2(key1, value1, key, value) - - def - (key: A): Map[A, B] = - if (key == key1) empty else this -} - - - diff --git a/src/library/scala/collection/immutable/Map2.scala b/src/library/scala/collection/immutable/Map2.scala deleted file mode 100644 index 2c97d0a3c3..0000000000 --- a/src/library/scala/collection/immutable/Map2.scala +++ /dev/null @@ -1,48 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - - -package scala.collection.immutable - -import Predef.Pair - -/** This class implements immutable maps with exactly two entries - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Map2[A, +B](key1: A, value1: B, key2: A, value2: B) extends Map[A, B] { - - def size = 2 - - def get(key: A): Option[B] = - if (key == key1) Some(value1) - else if (key == key2) Some(value2) - else None - - def elements = Iterator.fromValues( - (key1, value1), (key2, value2)) - - def empty[C]: Map[A, C] = new EmptyMap[A, C] - - def update [B1 >: B](key: A, value: B1): Map[A, B1] = - if (key == key1) new Map2(key1, value, key2, value2) - else if (key == key2) new Map2(key1, value1, key2, value) - else new Map3(key1, value1, key2, value2, key, value) - - def - (key: A): Map[A, B] = - if (key == key1) new Map1(key2, value2) - else if (key == key2) new Map1(key1, value1) - else this -} - - - diff --git a/src/library/scala/collection/immutable/Map3.scala b/src/library/scala/collection/immutable/Map3.scala deleted file mode 100644 index c8e6b470d8..0000000000 --- a/src/library/scala/collection/immutable/Map3.scala +++ /dev/null @@ -1,51 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - - -package scala.collection.immutable - -import Predef.Pair - -/** This class implements immutable maps with exactly three entries - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Map3[A, +B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B) extends Map[A, B] { - - def size = 3 - - def get(key: A): Option[B] = - if (key == key1) Some(value1) - else if (key == key2) Some(value2) - else if (key == key3) Some(value3) - else None - - def elements = Iterator.fromValues( - (key1, value1), (key2, value2), (key3, value3)) - - def empty[C]: Map[A, C] = new EmptyMap[A, C] - - def update [B1 >: B](key: A, value: B1): Map[A, B1] = - if (key == key1) new Map3(key1, value, key2, value2, key3, value3) - else if (key == key2) new Map3(key1, value1, key2, value, key3, value3) - else if (key == key3) new Map3(key1, value1, key2, value2, key3, value) - else new Map4(key1, value1, key2, value2, key3, value3, key, value) - - def - (key: A): Map[A, B] = - if (key == key1) new Map2(key2, value2, key3, value3) - else if (key == key2) new Map2(key1, value1, key3, value3) - else if (key == key3) new Map2(key1, value1, key2, value2) - else this -} - - - diff --git a/src/library/scala/collection/immutable/Map4.scala b/src/library/scala/collection/immutable/Map4.scala deleted file mode 100644 index cb8bf9f8eb..0000000000 --- a/src/library/scala/collection/immutable/Map4.scala +++ /dev/null @@ -1,52 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.immutable - -import Predef._ - -/** This class implements immutable maps with exactly four entries - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Map4[A, +B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B, key4: A, value4: B) extends Map[A, B] { - - def size = 4 - - def get(key: A): Option[B] = - if (key == key1) Some(value1) - else if (key == key2) Some(value2) - else if (key == key3) Some(value3) - else if (key == key4) Some(value4) - else None - - def elements = Iterator.fromValues( - (key1, value1), (key2, value2), (key3, value3), (key4, value4)) - - def empty[C]: Map[A, C] = new EmptyMap[A, C] - - def update [B1 >: B](key: A, value: B1): Map[A, B1] = - if (key == key1) new Map4(key1, value, key2, value2, key3, value3, key4, value4) - else if (key == key2) new Map4(key1, value1, key2, value, key3, value3, key4, value4) - else if (key == key3) new Map4(key1, value1, key2, value2, key3, value, key4, value4) - else if (key == key4) new Map4(key1, value1, key2, value2, key3, value3, key4, value) - else HashMap(key1 -> value1, key2 -> value2, key3 -> value3, key4 -> value4, key -> value) - - def - (key: A): Map[A, B] = - if (key == key1) new Map3(key2, value2, key3, value3, key4, value4) - else if (key == key2) new Map3(key1, value1, key3, value3, key4, value4) - else if (key == key3) new Map3(key1, value1, key2, value2, key4, value4) - else if (key == key4) new Map3(key1, value1, key2, value2, key3, value3) - else this -} - - - diff --git a/src/library/scala/collection/immutable/PagedSeq.scala b/src/library/scala/collection/immutable/PagedSeq.scala index c8d38e6b76..c63336f2da 100644 --- a/src/library/scala/collection/immutable/PagedSeq.scala +++ b/src/library/scala/collection/immutable/PagedSeq.scala @@ -163,7 +163,7 @@ class PagedSeq[T] protected (more: (Array[T], Int, Int) => Int, /** the subsequence from index `start' up to and excluding * the minimum of index `end' and the length of the current sequence. */ - override def slice(_start: Int, _end: Int) = { + override def slice(_start: Int, _end: Int): PagedSeq[T] = { page(start) val s = start + _start val e = if (_end == UndeterminedEnd) _end else start + _end diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index 1161c5b7fc..f7d2da9a09 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -178,3 +179,4 @@ class Queue[+A](elem: A*) extends Seq[A] { q._1.hashCode() + q._2.hashCode() } } +*/ diff --git a/src/library/scala/collection/immutable/RedBlack.scala b/src/library/scala/collection/immutable/RedBlack.scala index 9db5e0a4ca..efe85a12b1 100644 --- a/src/library/scala/collection/immutable/RedBlack.scala +++ b/src/library/scala/collection/immutable/RedBlack.scala @@ -28,10 +28,11 @@ abstract class RedBlack[A] { def lookup(x: A): Tree[B] def update[B1 >: B](k: A, v: B1): Tree[B1] = blacken(upd(k, v)) def delete(k: A): Tree[B] = del(k) - - def visit[T](input : T)(f : (T,A,B) => Tuple2[Boolean,T]) : Tuple2[Boolean,T]; - def elements : ImmutableIterator[Pair[A,B]]; - def elementsSlow: Iterator[Pair[A, B]]; + def foreach(f: (A, B) => Unit) + /** @deprecated use foreach instead */ + @deprecated def visit[T](input : T)(f : (T,A,B) => Tuple2[Boolean,T]) : Tuple2[Boolean,T]; + def toStream: Stream[(A,B)] + def elements: Iterator[Pair[A, B]] def upd[B1 >: B](k: A, v: B1): Tree[B1] def del(k: A): Tree[B] def smallest: NonEmpty[B] @@ -83,12 +84,20 @@ abstract class RedBlack[A] { } } def smallest: NonEmpty[B] = if (left.isEmpty) this else left.smallest - def elements : ImmutableIterator[Pair[A,B]] = - left.elements.append(Pair(key,value), () => right.elements) + def toStream: Stream[(A,B)] = + left.toStream append Stream((key,value)) append right.toStream + + def elements: Iterator[Pair[A, B]] = + left.elements append Iterator.single(Pair(key, value)) append right.elements - def elementsSlow: Iterator[Pair[A, B]] = - left.elementsSlow append Iterator.single(Pair(key, value)) append right.elementsSlow + def foreach(f: (A, B) => Unit) { + left foreach f + f(key, value) + right foreach f + } + /** @deprecated use foreach instead */ + @deprecated def visit[T](input : T)(f : (T,A,B) => Tuple2[Boolean,T]) : Tuple2[Boolean,T] = { val left = this.left.visit(input)(f) if (!left._1) return left @@ -120,8 +129,13 @@ abstract class RedBlack[A] { def upd[B](k: A, v: B): Tree[B] = RedTree(k, v, Empty, Empty) def del(k: A): Tree[Nothing] = this def smallest: NonEmpty[Nothing] = throw new NoSuchElementException("empty map") - def elementsSlow: Iterator[Pair[A, Nothing]] = Iterator.empty - def elements : ImmutableIterator[Pair[A,Nothing]] = ImmutableIterator.empty + def elements: Iterator[Pair[A, Nothing]] = Iterator.empty + def toStream: Stream[(A,Nothing)] = Stream.empty + + def foreach(f: (A, Nothing) => Unit) {} + + /** @deprecated use foreach instead */ + @deprecated def visit[T](input : T)(f : (T,A,Nothing) => Tuple2[Boolean,T]) = Tuple2(true,input) def range(from : Option[A], until : Option[A]) = this diff --git a/src/library/scala/collection/immutable/Sequence.scala b/src/library/scala/collection/immutable/Sequence.scala new file mode 100755 index 0000000000..5265912e11 --- /dev/null +++ b/src/library/scala/collection/immutable/Sequence.scala @@ -0,0 +1,26 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.collection.immutable + +import generic._ + +/** A subtrait of collection.Sequence which represents sequences + * that cannot be mutated. + */ +trait Sequence[+A] extends Iterable[A] with collection.Sequence[A] with SequenceTemplate[A, Sequence[A]] { + override protected[this] def newBuilder = Sequence.newBuilder + override def traversibleBuilder[B]: Builder[B, Sequence[B], Any] = Sequence.newBuilder[B] + override def hashCode = (Sequence.hashSeed /: this)(_ * 41 + _.hashCode) +} + +object Sequence extends SequenceFactory[Sequence] { + private val hashSeed = "Sequence".hashCode + type Coll = Sequence[_] + implicit def builderFactory[A]: BuilderFactory[A, Sequence[A], Coll] = new BuilderFactory[A, Sequence[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Sequence[A], Any] = new mutable.ListBuffer +} diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala index 474e541f65..5819d38e03 100644 --- a/src/library/scala/collection/immutable/Set.scala +++ b/src/library/scala/collection/immutable/Set.scala @@ -11,177 +11,23 @@ package scala.collection.immutable +import generic._ -/** Canonical factories for immutable sets. The canonical immutable sets are - * currently implemented using <a href="HashSet.html">immutable hash sets</a>. - */ -object Set { - /** The empty set of this type - */ - def empty[A]: Set[A] = new EmptySet[A] - - /** The canonical factory for this type - */ - def apply[A](elems: A*) = empty[A] ++ elems -} - -/** <p> - * This class defines the interface for immutable sets. Operations - * on an immutable set leave the original set unchanged, and return - * a new set if needed. - * </p> - * <p> - * Concrete set implementations just have to provide functionality for - * the abstract methods in <code>scala.collection.Set</code> as well as - * for <code>+</code> and <code>-</code>. - * </p> - * <p> - * Note that abstract immutable.Set's are not covariant in their type - * parameter. This is because some implementations cannot support the - * <code>+</code> method for arbitrary types. - * </p> - * - * @author Matthias Zenger, Martin Odersky - * @version 1.1, 03/05/2004 +/** A generic trait for immutable sets */ -trait Set[A] extends AnyRef with collection.Set[A] { - - /** @return an empty set of arbitrary element type - */ - def empty[B]: Set[B] - - /** Create a new set with an additional element. - */ - def +(elem: A): Set[A] - - /** Add two or more elements to this set. - * @param elem1 the first element. - * @param elem2 the second element. - * @param elems the remaining elements. - * @return a new set with the elements added. - */ - def + (elem1: A, elem2: A, elems: A*): Set[A] = - this + elem1 + elem2 ++ elems - - /** Add all the elements provided by an iterator - * of the iterable object <code>elems</code> to the set. - * - * @param elems the iterable object containing the elements to be added - * @return a new set with the elements added. - */ - def ++ (elems: Iterable[A]): Set[A] = - (this /: elems) ((s, elem) => s + elem) - - /** Add all the elements provided by an iterator to the set. - * @param elems the iterator containing the elements to be added - * @return a new set with the elements added. - */ - def ++ (elems: Iterator[A]): Set[A] = - (this /: elems) ((s, elem) => s + elem) - - /** <code>incl</code> can be used to add many elements to the set - * at the same time. - * @deprecated use <code>+</code> instead - */ - @deprecated - def incl(elems: A*): Set[A] = incl(elems) - - /** This method will add all the elements provided by an iterator - * of the iterable object <code>that</code> to the set. - * @deprecated use <code>++</code> instead - */ - @deprecated - def incl(that: Iterable[A]): Set[A] = - that.foldLeft(this)((set, elem) => set + elem) +trait Set[A] extends Iterable[A] with collection.Set[A] with SetTemplate[A, Set[A]] { self => - /** Remove a single element from a set. - * @param elem the element to be removed - * @return a new set with the element removed. - */ - def -(elem: A): Set[A] + override def empty = Set.empty - /** Remove two or more elements from this set. - * - * @param elem1 the first element. - * @param elem2 the second element. - * @param elems the remaining elements. - * @return a new set with the elements removed. - */ - def - (elem1: A, elem2: A, elems: A*): Set[A] = - this - elem1 - elem2 -- elems + override def hashCode = (Set.hashSeed /: this)(_ * 41 + _.hashCode) - /** Remove all the elements provided by an iterator - * of the iterable object <code>elems</code> from the set. - * - * @param elems An iterable object containing the elements to remove from the set. - * @return a new set with the elements removed. - */ - def -- (elems: Iterable[A]): Set[A] = this -- elems.elements - - /** Remove all the elements provided by an iterator - * <code>elems</code> from the set. - * - * @param elems An iterator containing the elements to remove from the set. - * @return a new set with the elements removed. - */ - def -- (elems: Iterator[A]): Set[A] = - (this /: elems) ((s, elem) => s - elem) - - /** <code>excl</code> removes many elements from the set. - */ - @deprecated - def excl(elems: A*): Set[A] = excl(elems) - - /** This method removes all the elements provided by an iterator - * of the iterable object <code>that</code> from the set. - * - * @param that the iterable collection. - */ - @deprecated - def excl(that: Iterable[A]): Set[A] = - that.foldLeft(this)((set, elem) => set - elem) - - /** This method computes an intersection with set <code>that</code>. - * It removes all the elements that are not present in <code>that</code>. - * - * @param that the set to intersect with. - */ - def intersect(that: collection.Set[A]): Set[A] = filter(that.contains) - - /** This method is an alias for <code>intersect</code>. - * It computes an intersection with set <code>that</code>. - * It removes all the elements that are not present in <code>that</code>. - * - * @param that the set to intersect with - */ - override def ** (that: collection.Set[A]): Set[A] = intersect(that) - - /** Returns the set resulting from applying the given function <code>f</code> to each - * element of this set. - * - * @param f function to apply to each element. - * @return a set containing <code>f(a0), ..., f(an)</code> - * if this set contains <code>a0, ..., an</code>. - */ - override def map[B](f: A => B): Set[B] = - foldLeft(empty[B])((set: Set[B], elem: A) => set + f(elem)) - - /** Applies the given function <code>f</code> to each element of - * this set, then forms the union of all results. - * - * @param f function to apply to each element. - * @return a set containing all elements in each <code>f(a0), ..., f(an)</code> - * if this set contains <code>a0, ..., an</code>. - */ - override def flatMap[B](f: A => Iterable[B]): Set[B] = - foldLeft(empty[B])((set: Set[B], elem: A) => set ++ f(elem)) - - /** Method <code>filter</code> removes all elements from the set for - * which the predicate <code>p</code> yields the value <code>false</code>. - * - * @param p The predicate used to filter the set - */ - override def filter(p: A => Boolean): Set[A] = - (this /: toList)((set, elem) => if (p(elem)) set else set - elem) + override def traversibleBuilder[B]: Builder[B, Set[B], Any] = Set.newBuilder[B] +} +object Set extends SetFactory[Set] { + private val hashSeed = "Set".hashCode + type Coll = Set[_] + implicit def builderFactory[A]: BuilderFactory[A, Set[A], Coll] = new BuilderFactory[A, Set[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def empty[A]: Set[A] = FlexSet.empty } + diff --git a/src/library/scala/collection/immutable/Set1.scala b/src/library/scala/collection/immutable/Set1.scala deleted file mode 100644 index 8d6e9b50ca..0000000000 --- a/src/library/scala/collection/immutable/Set1.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - - -package scala.collection.immutable - -/** This class implements immutable sets with exactly one element. - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Set1[A](elem1: A) extends Set[A] { - - def empty[C]: Set[C] = new EmptySet[C] - - def size: Int = 1 - - def contains(elem: A): Boolean = - elem == elem1 - - def + (elem: A): Set[A] = - if (contains(elem)) this - else new Set2(elem1, elem) - - def - (elem: A): Set[A] = - if (elem == elem1) empty - else this - - def elements: Iterator[A] = - Iterator.fromValues(elem1) -} - - - diff --git a/src/library/scala/collection/immutable/Set2.scala b/src/library/scala/collection/immutable/Set2.scala deleted file mode 100644 index d5e83779f5..0000000000 --- a/src/library/scala/collection/immutable/Set2.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - - -package scala.collection.immutable - -/** This class implements immutable sets with exactly two elements. - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Set2[A](elem1: A, elem2: A) extends Set[A] { - - def empty[C]: Set[C] = new EmptySet[C] - - def size: Int = 2 - - def contains(elem: A): Boolean = - elem == elem1 || elem == elem2 - - def + (elem: A): Set[A] = - if (contains(elem)) this - else new Set3(elem1, elem2, elem) - - def - (elem: A): Set[A] = - if (elem == elem1) new Set1(elem2) - else if (elem == elem2) new Set1(elem1) - else this - - def elements: Iterator[A] = - Iterator.fromValues(elem1, elem2) -} - - - diff --git a/src/library/scala/collection/immutable/Set3.scala b/src/library/scala/collection/immutable/Set3.scala deleted file mode 100644 index e692bce362..0000000000 --- a/src/library/scala/collection/immutable/Set3.scala +++ /dev/null @@ -1,44 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - - -package scala.collection.immutable - -/** This class implements immutable sets with exactly three elements. - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Set3[A](elem1: A, elem2: A, elem3: A) extends Set[A] { - - def empty[C]: Set[C] = new EmptySet[C] - - def size: Int = 3 - - def contains(elem: A): Boolean = - elem == elem1 || elem == elem2 || elem == elem3 - - def + (elem: A): Set[A] = - if (contains(elem)) this - else new Set4(elem1, elem2, elem3, elem) - - def - (elem: A): Set[A] = - if (elem == elem1) new Set2(elem2, elem3) - else if (elem == elem2) new Set2(elem1, elem3) - else if (elem == elem3) new Set2(elem1, elem2) - else this - - def elements: Iterator[A] = - Iterator.fromValues(elem1, elem2, elem3) -} - - - diff --git a/src/library/scala/collection/immutable/Set4.scala b/src/library/scala/collection/immutable/Set4.scala deleted file mode 100644 index f4ec9e7078..0000000000 --- a/src/library/scala/collection/immutable/Set4.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - - -package scala.collection.immutable - -/** This class implements immutable sets with exactly four elements. - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Set4[A](elem1: A, elem2: A, elem3: A, elem4: A) extends Set[A] { - - def empty[C]: Set[C] = new EmptySet[C] - - def size: Int = 4 - - def contains(elem: A): Boolean = - elem == elem1 || elem == elem2 || elem == elem3 || elem == elem4 - - def + (elem: A): Set[A] = - if (contains(elem)) this - else HashSet(elem1, elem2, elem3, elem4, elem) - - def - (elem: A): Set[A] = - if (elem == elem1) new Set3(elem2, elem3, elem4) - else if (elem == elem2) new Set3(elem1, elem3, elem4) - else if (elem == elem3) new Set3(elem1, elem2, elem4) - else if (elem == elem4) new Set3(elem1, elem2, elem3) - else this - - def elements: Iterator[A] = - Iterator.fromValues(elem1, elem2, elem3, elem4) -} - - - diff --git a/src/library/scala/collection/immutable/SortedMap.scala b/src/library/scala/collection/immutable/SortedMap.scala index c18d08e3a3..85b01561a7 100644 --- a/src/library/scala/collection/immutable/SortedMap.scala +++ b/src/library/scala/collection/immutable/SortedMap.scala @@ -8,53 +8,55 @@ // $Id$ -package scala.collection.immutable - -trait SortedMap[A,+B] extends Map[A,B] with collection.SortedMap[A,B] { - - override def rangeImpl(from: Option[A], until: Option[A]): SortedMap[A,B] - - override def from(from: A) = rangeImpl(Some(from), None) - - override def until(until: A) = rangeImpl(None, Some(until)) - - override def range(from: A, until: A) = rangeImpl(Some(from),Some(until)) - - override def empty[C]: SortedMap[A, C] - - override def update [B1 >: B] (key: A, value: B1): SortedMap[A, B1] - - override def + [B1 >: B] (kv: Pair[A, B1]): SortedMap[A, B1] = update(kv._1, kv._2) - override def + [B1 >: B] (kv1: Pair[A, B1], kv2: Pair[A, B1], kvs: Pair[A, B1]*): SortedMap[A, B1] = - this + kv1 + kv2 ++ kvs - - override def ++ [B1 >: B] (kvs: Iterable[Pair[A, B1]]): SortedMap[A, B1] = - ((this: SortedMap[A, B1]) /: kvs) ((m, kv) => m + kv) - - override def ++ [B1 >: B] (kvs: Iterator[Pair[A, B1]]): SortedMap[A, B1] = - ((this: SortedMap[A, B1]) /: kvs) ((m, kv) => m + kv) - - override def - (key: A): SortedMap[A, B] - - override def - (key1: A, key2: A, keys: A*): SortedMap[A, B] = - this - key1 - key2 -- keys - - override def -- (keys: Iterable[A]): SortedMap[A, B] = this -- keys.elements - - override def -- (keys: Iterator[A]): SortedMap[A, B] = - (this /: keys) ((m, key) => m - key) +/** A map whose keys are sorted. + * + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ +package scala.collection.immutable - override def transform[C](f: (A, B) => C): SortedMap[A, C] = { - var res = empty[C] - foreach { case (key, value) => res = res.update(key, f(key, value)) } - res - } - override def filter(p: Pair[A, B] => Boolean): SortedMap[A, B] = { - var res = this - foreach { - case kv @ (key, _) => if (!p(kv)) { res = res - key } - } - res +import generic._ +import annotation.unchecked.uncheckedVariance + +trait SortedMap[A, +B] extends Map[A, B] + with collection.SortedMap[A, B] + with ImmutableMapTemplate[A, B, SortedMap[A, B]] + with SortedMapTemplate[A, B, SortedMap[A, B]] { + + /** Needs to be overridden in subclasses. */ + override def empty: SortedMap[A, B] = throw new UnsupportedOperationException("SortedMap.empty") + + /** Needs to be overridden in subclasses. */ + override protected[this] def newBuilder : Builder[(A, B), SortedMap[A, B], Any] = + throw new UnsupportedOperationException("SortedMap.newBuilder") + + /** Add a key/value pair to this map. + * @param key the key + * @param value the value + * @return A new map with the new binding added to this map + */ + def add [B1 >: B](key: A, value: B1): SortedMap[A, B1] + + /** Add a key/value pair to this map. + * @param kv the key/value pair + * @return A new map with the new binding added to this map + */ + override def + [B1 >: B] (kv: (A, B1)): SortedMap[A, B1] = add(kv._1, kv._2) + + /** Adds two or more elements to this collection and returns + * either the collection itself (if it is mutable), or a new collection + * with the added elements. + * + * @param elem1 the first element to add. + * @param elem2 the second element to add. + * @param elems the remaining elements to add. + */ + override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): SortedMap[A, B1] = { + var m = this + elem1 + elem2; + for (e <- elems) m = m + e + m } } + diff --git a/src/library/scala/collection/immutable/SortedSet.scala b/src/library/scala/collection/immutable/SortedSet.scala index 1aae9a4987..911cfcba0a 100644 --- a/src/library/scala/collection/immutable/SortedSet.scala +++ b/src/library/scala/collection/immutable/SortedSet.scala @@ -8,10 +8,17 @@ // $Id$ +/** A sorted set. + * + * @author Sean McDirmid + * @author Martin Odersky + * @version 2.8 + */ package scala.collection.immutable -trait SortedSet[A] extends scala.collection.SortedSet[A] with Set[A] { - override def ++ (elems: Iterable[A]): SortedSet[A] = - (this /: elems) ((s, elem) => s + elem) - override def +(elem: A): SortedSet[A] +import generic._ + +trait SortedSet[A] extends Set[A] with collection.SortedSet[A] with SortedSetTemplate[A, SortedSet[A]] { + /** Needs to be overridden in subclasses. */ + override def empty: SortedSet[A] = throw new UnsupportedOperationException("SortedMap.empty") } diff --git a/src/library/scala/collection/immutable/Stack.scala b/src/library/scala/collection/immutable/Stack.scala index 4b507daafe..07ff59100f 100644 --- a/src/library/scala/collection/immutable/Stack.scala +++ b/src/library/scala/collection/immutable/Stack.scala @@ -22,12 +22,14 @@ object Stack { * structure. Instances of <code>Stack</code> represent * empty stacks; they can be either created by calling the constructor * directly, or by applying the function <code>Stack.Empty</code>. + * @note This class exists only for historical reason and as an analogue of mutable stacks + * Instead of an immutable stack you can just use a list. * * @author Matthias Zenger * @version 1.0, 10/07/2003 */ @serializable -class Stack[+A] extends Seq[A] { +class Stack[+A] extends Sequence[A] { /** Checks if this stack is empty. * @@ -35,24 +37,12 @@ class Stack[+A] extends Seq[A] { */ override def isEmpty: Boolean = true - /** Returns the size of this stack. - * - * @return the stack size. + /** The number of elements in the stack */ def length: Int = 0 /** Push an element on the stack. * - * @deprecated Use the method <code>push</code> from now on. - * - * @param elem the element to push on the stack. - * @return the stack with the new element on top. - */ - @deprecated - def +[B >: A](elem: B): Stack[B] = new Node(elem) - - /** Push an element on the stack. - * * @param elem the element to push on the stack. * @return the stack with the new element on top. */ @@ -65,29 +55,7 @@ class Stack[+A] extends Seq[A] { * @return the stack with the new elements on top. */ def push[B >: A](elem1: B, elem2: B, elems: B*): Stack[B] = - this.push(elem1).push(elem2) ++ elems - - /** Push all elements provided by the given iterable object onto - * the stack. The last element returned by the iterable object - * will be on top of the new stack. - * - * @deprecated Use the method <code>push</code> from now on. - * - * @param elems the iterable object. - * @return the stack with the new elements on top. - */ - @deprecated - def +[B >: A](elems: Iterable[B]): Stack[B] = - elems.foldLeft(this: Stack[B]){ (stack, elem) => stack + elem } - - /** Push all elements provided by the given iterable object onto - * the stack. The last element returned by the iterable object - * will be on top of the new stack. - * - * @param elems the iterable object. - * @return the stack with the new elements on top. - */ - def push[B >: A](elems: Iterable[B]): Stack[B] = this ++ elems + this.push(elem1).push(elem2).pushAll(elems) /** Push all elements provided by the given iterator object onto * the stack. The last element returned by the iterable object @@ -97,31 +65,31 @@ class Stack[+A] extends Seq[A] { * @return the stack with the new elements on top. * @deprecated */ - def ++[B >: A](elems: Iterator[B]): Stack[B] = - elems.foldLeft(this: Stack[B]){ (stack, elem) => stack push elem } + def pushAll[B >: A](elems: Iterator[B]): Stack[B] = + ((this: Stack[B]) /: elems)(_ push _) - /** Push all elements provided by the given iterable object onto + /** Push all elements provided by the given traversible object onto * the stack. The last element returned by the iterable object * will be on top of the new stack. * * @param elems the iterable object. * @return the stack with the new elements on top. */ - override def ++[B >: A](elems: Iterable[B]): Stack[B] = - this ++ elems.elements + def pushAll[B >: A](elems: collection.Traversible[B]): Stack[B] = + ((this: Stack[B]) /: elems)(_ push _) /** Returns the top element of the stack. An error is signaled if * there is no element on the stack. * * @return the top element. */ - def top: A = throw new NoSuchElementException("no element on stack") + def top: A = throw new NoSuchElementException("top of empty stack") /** Removes the top element from the stack. * * @return the new stack without the former top element. */ - def pop: Stack[A] = throw new NoSuchElementException("no element on stack") + def pop: Stack[A] = throw new NoSuchElementException("pop of empty stack") /** Returns the n-th element of this stack. The bottom element has index * 0, elements above are indexed with increasing numbers. @@ -129,11 +97,7 @@ class Stack[+A] extends Seq[A] { * @param n the index number. * @return the n-th element on the stack. */ - def apply(n: Int): A = reverse.reverseApply(n) - - private def reverseApply(n: Int): A = - if (n > 0) pop.reverseApply(n - 1) - else top + def apply(n: Int): A = if (n <= 0) top else pop.apply(n - 1) /** Returns an iterator over all elements on the stack. The iterator * issues elements in the reversed order they were inserted into the @@ -141,58 +105,30 @@ class Stack[+A] extends Seq[A] { * * @return an iterator over all stack elements. */ - override def elements: Iterator[A] = reverse.reverseElements - - private def reverseElements: Iterator[A] = new Iterator[A] { - var that: Stack[A] = Stack.this; - def hasNext = !that.isEmpty; - def next = - if (!hasNext) throw new NoSuchElementException("next on empty iterator") - else { val res = that.top; that = that.pop; res } - } - - /** A stack consisting of all elements of this stack in reverse order. - */ - override def reverse: Stack[A] = { - // copy-paste from List.reverse - var result: Stack[A] = Stack.Empty - var these = this - while (!these.isEmpty) { - result = result push List(these.top) // see #978 - these = these.pop - } - result - } - - /** Compares this stack with the given object. - * - * @return true, iff the two stacks are equal; i.e. they contain the - * same elements in the same order. - */ - override def equals(obj: Any): Boolean = obj match { - case that: Stack[_] => this sameElements that - case _ => false + override def elements: Iterator[A] = new Iterator[A] { + private var cur = Stack.this + def hasNext: Boolean = !cur.isEmpty + def next: A = { val r = top; cur = cur.pop; r } } /** Returns the hash code for this stack. * * @return the hash code of the stack. */ - override def hashCode(): Int = 0 + override def hashCode(): Int = "Stack".hashCode /** * Redefines the prefix of the string representation. */ override def stringPrefix: String = "Stack" - // Here comes true magic: covariant lists with implicit tail references @serializable protected class Node[+B >: A](elem: B) extends Stack[B] { override def isEmpty: Boolean = false override def length: Int = Stack.this.length + 1 override def top: B = elem override def pop: Stack[B] = Stack.this - override def hashCode(): Int = elem.hashCode() + Stack.this.hashCode() + override def hashCode(): Int = elem.hashCode() * 37 + Stack.this.hashCode() } - } + diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala new file mode 100755 index 0000000000..656252c282 --- /dev/null +++ b/src/library/scala/collection/immutable/Stream.scala @@ -0,0 +1,561 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Stream.scala 16287 2008-10-18 13:41:36Z nielsen $ + + +package scala.collection.immutable + +import mutable.ListBuffer +import generic.{SequenceFactory, Builder, BuilderFactory, LazyBuilder, LinearSequenceTemplate} + +/** + * <p>The class <code>Stream</code> implements lazy lists where elements + * are only evaluated when they are needed. Here is an example:</p> + * <pre> + * <b>object</b> Main <b>extends</b> Application { + * + * <b>def</b> from(n: Int): Stream[Int] = + * Stream.cons(n, from(n + 1)) + * + * <b>def</b> sieve(s: Stream[Int]): Stream[Int] = + * Stream.cons(s.head, sieve(s.tail filter { _ % s.head != 0 })) + * + * <b>def</b> primes = sieve(from(2)) + * + * primes take 10 print + * } + * </pre> + * + * @author Martin Odersky, Matthias Zenger + * @version 1.1 08/08/03 + */ +abstract class Stream[+A] extends LinearSequence[A] with LinearSequenceTemplate[A, Stream[A]] { +self => + import collection.{Traversible, Iterable, Sequence, Vector} + + /** is this stream empty? */ + def isEmpty: Boolean + + /** The first element of this stream + * @throws Predef.NoSuchElementException if the stream is empty. + */ + def head: A + + /** A stream consisting of the remaining elements of this stream after the first one. + * @throws Predef.UnsupportedOperationException if the stream is empty. + */ + def tail: Stream[A] + + /** Is the tail of this stream defined? */ + protected def tailDefined: Boolean + + // Implementation of abstract method in Traversible + + /** The builder for stream objects. + * @note: This builder is lazy only in the sense that it does not go downs the spine + * of traversibles taht are added as a whole. If more layzness can be achieved, + * this builder should be bypassed. + */ + override protected[this] def newBuilder = Stream.newBuilder + override def traversibleBuilder[B]: Builder[B, Stream[B], Any] = Stream.newBuilder[B] + + // New methods in Stream + + /** The stream resulting from the concatenation of this stream with the argument stream. + * @param rest The stream that gets appended to this stream + */ + def append[B >: A](rest: => Traversible[B]): Stream[B] = + if (isEmpty) rest.toStream else new Stream.Cons(head, tail append rest) + + /** Force evaluation of the whole stream and return it */ + def force: Stream[A] = { + var these = this + while (!isEmpty) these = these.tail + this + } + + /** Does this stream have more than one elements defined? + */ + private def hasMoreThanOneElements = false + + /** Prints elements of this stream one by one, separated by commas */ + def print() { print(", ") } + + /** Prints elements of this stream one by one, separated by <code>sep</code> + * @param sep The separator string printed between consecutive elements. + */ + def print(sep: String) { + def loop(these: Stream[A], start: String) { + Console.print(start) + if (these.isEmpty) Console.print("empty") + else { + Console.print(these.head) + loop(these.tail, sep) + } + } + loop(this, "") + } + + // Overridden methods from Traversible + + override def toStream: Stream[A] = this + + override def hasDefiniteSize = { + def loop(s: Stream[A]): Boolean = s.isEmpty || s.tailDefined && loop(s.tail) + loop(this) + } + + /** Create a new stream which contains all elements of this stream + * followed by all elements of Traversible `that' + * @note It's subtle why this works. We know that if the target type + * of the Builder That is either a Stream, or one of its supertypes, or undefined, + * then StreamBuilder will be chosen for the implicit. + * we recognize that fact and optimize to get more laziness. + */ + override def ++[B >: A, That](that: Traversible[B])(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { + def loop(these: Stream[A]): Stream[B] = + if (these.isEmpty) that.toStream else new Stream.Cons(these.head, loop(these.tail)) + if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] + else super.++(that) + } + + /** Create a new stream which contains all elements of this stream + * followed by all elements of Iterator `that' + */ + override def++[B >: A, That](that: Iterator[B])(implicit bf: BuilderFactory[B, That, Stream[A]]): That = + this ++ that.toStream + + /** Returns the stream resulting from applying the given function + * <code>f</code> to each element of this stream. + * + * @param f function to apply to each element. + * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> if this + * sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. + */ + override def map[B, That](f: A => B)(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { + def loop(these: Stream[A]): Stream[B] = + if (these.isEmpty) Stream.Empty else new Stream.Cons(f(these.head), loop(these.tail)) + if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] + else super.map(f) + } + + /** Applies the given function <code>f</code> to each element of + * this stream, then concatenates the results. + * + * @param f the function to apply on each element. + * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if + * this stream is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>. + */ + override def flatMap[B, That](f: A => Traversible[B])(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { + def loop(these: Stream[A]): Stream[B] = + if (these.isEmpty) Stream.Empty + else { + val seg = f(these.head) + if (seg.isEmpty) loop(these.tail) + else seg.toStream ++ loop(these.tail) + } + if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] + else super.flatMap(f) + } + + /** Returns all the elements of this stream that satisfy the + * predicate <code>p</code>. The order of the elements is preserved. + * + * @param p the predicate used to filter the stream. + * @return the elements of this stream satisfying <code>p</code>. + */ + override def filter(p: A => Boolean): Stream[A] = { + // drops A's for which p yields false + def loop(these: Stream[A]): Stream[A] = + if (these.isEmpty) Stream.Empty + else { + val b = p(these.head) + if (!b) loop(these.tail) + else new Stream.Cons(these.head, these.tail filter p) + } + loop(this) + } + + /** Returns all the elements of this stream that satisfy the + * predicate <code>p</code>. The order of the elements is preserved. + * + * @param p the predicate used to filter the stream. + * @return the elements of this stream satisfying <code>p</code>. + */ + override def partition(p: A => Boolean): (Stream[A], Stream[A]) = (filter(p(_)), remove(p(_))) + + /** Returns a stream formed from this stream and the specified stream + * <code>that</code> by associating each element of the former with + * the element at the same position in the latter. + * If one of the two streams is longer than the other, its remaining elements are ignored. + * + * @return <code>Stream({a<sub>0</sub>,b<sub>0</sub>}, ..., + * {a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>)}</code> when + * <code>Stream(a<sub>0</sub>, ..., a<sub>m</sub>) + * zip Stream(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked. + */ + override def zip[A1 >: A, B, That](that: Sequence[B])(implicit bf: BuilderFactory[(A1, B), That, Stream[A]]): That = { + def loop(these: Stream[A], elems2: Iterator[B]): Stream[(A1, B)] = + if (these.isEmpty || !elems2.hasNext) Stream.Empty + else new Stream.Cons((these.head, elems2.next), loop(these.tail, elems2)) + if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this, that.elements).asInstanceOf[That] + else super.zip[A1, B, That](that) + } + + /** Zips this iterable with its indices. `s.zipWithIndex` is equivalent to + * `s zip s.indices` + */ + override def zipWithIndex[A1 >: A, That](implicit bf: BuilderFactory[(A1, Int), That, Stream[A]]): That = + this.zip[A1, Int, That](Stream.from(0)) + + /** Write all defined elements of this iterable into given string builder. + * The written text begins with the string <code>start</code> and is finished by the string + * <code>end</code>. Inside, the string representations of defined elements (w.r.t. + * the method <code>toString()</code>) are separated by the string + * <code>sep</code>. The method will not force evaluation of undefined elements. A + * tail of such elements will be represented by a "?" instead. + */ + override def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = { + def loop(pre: String, these: Stream[A]) { + if (these.isEmpty) b append end + else { + b append pre append these.head + if (these.tailDefined) loop(sep, these.tail) + else b append sep append "?" append end + } + } + b append start + loop("", this) + b + } + + /** Returns the <code>n</code> first elements of this stream, or else the whole + * stream, if it has less than <code>n</code> elements. + * + * @param n the number of elements to take. + * @return the <code>n</code> first elements of this stream. + */ + override def take(n: Int): Stream[A] = + if (n <= 0 || isEmpty) Stream.Empty else new Stream.Cons(head, tail take (n-1)) + + /** Returns the stream without its <code>n</code> first elements. + * If the stream has less than <code>n</code> elements, the empty stream is returned. + * + * @param n the number of elements to drop. + * @return the stream without its <code>n</code> first elements. + */ + override def drop(n: Int): Stream[A] = { + var these: Stream[A] = this + var count = n + while (!these.isEmpty && count > 0) { + these = these.tail + count -= 1 + } + these + } + + /** A substream starting at index `from` + * and extending up to (but not including) index `until`. + * + * @note This is equivalent to (but possibly more efficient than) + * c.drop(from).take(to - from) + * + * @param start The index of the first element of the returned subsequence + * @param end The index of the element following the returned subsequence + * @throws IndexOutOfBoundsException if <code>from < 0</code> + * or <code>length < from + len<code> + * @note Might return different results for different runs, unless this iterable is ordered + */ + override def slice(start: Int, end: Int): Stream[A] = { + var len = end + if (start > 0) len -= start + drop(start) take len + } + + /** The stream without its last element. + * @throws Predef.UnsupportedOperationException if the stream is empty. + */ + override def init: Stream[A] = + if (isEmpty) super.init + else if (tail.isEmpty) Stream.Empty + else new Stream.Cons(head, tail.init) + + /** Returns the rightmost <code>n</code> elements from this iterable. + * @param n the number of elements to take + */ + override def takeRight(n: Int): Stream[A] = { + var these: Stream[A] = this + var lead = this drop n + while (!lead.isEmpty) { + these = these.tail + lead = lead.tail + } + these + } + + // there's nothing we can do about dropRight, so we just keep the definition in LinearSequence + + /** Returns the longest prefix of this stream whose elements satisfy + * the predicate <code>p</code>. + * + * @param p the test predicate. + */ + override def takeWhile(p: A => Boolean): Stream[A] = + if (!isEmpty && p(head)) new Stream.Cons(head, tail takeWhile p) + else Stream.Empty + + /** Returns the longest suffix of this iterable whose first element + * does not satisfy the predicate <code>p</code>. + * + * @param p the test predicate. + */ + override def dropWhile(p: A => Boolean): Stream[A] = { + var these: Stream[A] = this + while (!these.isEmpty && p(these.head)) these = these.tail + these + } + + /** Builds a new stream from this stream in which any duplicates (wrt to ==) removed. + * Among duplicate elements, only the first one is retained in the result stream + */ + override def removeDuplicates: Stream[A] = + if (isEmpty) this + else new Stream.Cons(head, tail.filter(head !=).removeDuplicates) + + /** Returns a new sequence of given length containing the elements of this sequence followed by zero + * or more occurrences of given elements. + */ + override def padTo[B >: A, That](len: Int, elem: B)(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { + def loop(len: Int, these: Stream[A]): Stream[B] = + if (these.isEmpty) Stream.fill(len)(elem) + else new Stream.Cons(these.head, loop(len - 1, these.tail)) + if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(len, this).asInstanceOf[That] + else super.padTo(len, elem) + } + + /** A list consisting of all elements of this list in reverse order. + */ + override def reverse: Stream[A] = { + var result: Stream[A] = Stream.Empty + var these = this + while (!these.isEmpty) { + val r = Stream.consWrapper(result).#::(these.head) + r.tail // force it! + result = r + these = these.tail + } + result + } + + /** Defines the prefix of this object's <code>toString</code> representation as ``Stream''. + */ + override def stringPrefix = "Stream" +} + +/** + * The object <code>Stream</code> provides helper functions + * to manipulate streams. + * + * @author Martin Odersky, Matthias Zenger + * @version 1.1 08/08/03 + */ +object Stream extends SequenceFactory[Stream] { + + type Coll = Stream[_] + class StreamBuilderFactory[A] extends BuilderFactory[A, Stream[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + implicit def builderFactory[A]: BuilderFactory[A, Stream[A], Coll] = new StreamBuilderFactory[A] + + /** Creates a new builder for a stream */ + def newBuilder[A]: Builder[A, Stream[A], Any] = new StreamBuilder[A] + + import collection.{Iterable, Sequence, Vector} + + /** A builder for streams + */ + class StreamBuilder[A] extends LazyBuilder[A, Stream[A], Any] { + def result: Stream[A] = (for (xs <- parts.elements; x <- xs.toIterable.elements) yield x).toStream + } + + object Empty extends Stream[Nothing] { + override def isEmpty = true + override def head = throw new NoSuchElementException("head of empty stream") + override def tail = throw new UnsupportedOperationException("tail of empty stream") + def tailDefined = false + } + + /** The empty stream */ + override def empty[A]: Stream[A] = Empty + + /** A stream consisting of given elements */ + override def apply[A](xs: A*): Stream[A] = Iterable.fromOld(xs).toStream + + /** A wrapper class that adds `#::` for cons and `#:::` for concat as operations + * to streams. + */ + class ConsWrapper[A](tl: => Stream[A]) { + def #::(hd: A): Stream[A] = new Stream.Cons(hd, tl) + def #:::(prefix: Stream[A]): Stream[A] = prefix append tl + } + + /** A wrapper method that adds `#::` for cons and `#::: for concat as operations + * to streams. + */ + implicit def consWrapper[A](stream: => Stream[A]): ConsWrapper[A] = + new ConsWrapper[A](stream) + + /** An extractor that allows to pattern match streams with `#::`. + */ + object #:: { + def unapply[A](xs: Stream[A]): Option[(A, Stream[A])] = + if (xs.isEmpty) None + else Some((xs.head, xs.tail)) + } + + /** @deprecated use #:: instead */ + @deprecated lazy val lazy_:: = #:: + + /** An alternative way of building and matching Streams using Stream.cons(hd, tl). + */ + object cons { + + /** A stream consisting of a given first element and remaining elements + * @param hd The first element of the result stream + * @param tl The remaining elements of the result stream + */ + def apply[A](hd: A, tl: => Stream[A]) = new Cons(hd, tl) + + /** Maps a stream to its head and tail */ + def unapply[A](xs: Stream[A]): Option[(A, Stream[A])] = #::.unapply(xs) + } + + /** A lazy cons cell, from which streams are built. */ + final class Cons[+A](hd: A, tl: => Stream[A]) extends Stream[A] { + override def isEmpty = false + override def head = hd + private[this] var tlVal: Stream[A] = _ + def tailDefined = tlVal ne null + override def tail: Stream[A] = { + if (!tailDefined) { tlVal = tl } + tlVal + } + } + + /** An infinite stream that repeatedly applies a given function to a start value. + * + * @param start the start value of the stream + * @param f the function that's repeatedly applied + * @return the stream returning the infinite sequence of values `start, f(start), f(f(start)), ...` + */ + def iterate(start: Int)(f: Int => Int): Stream[Int] = new Cons(start, iterate(f(start))(f)) + + override def iterate(start: Int, len: Int)(f: Int => Int): Stream[Int] = iterate(start)(f) take len + + /** + * Create an infinite stream starting at <code>start</code> + * and incrementing by step <code>step</code> + * + * @param start the start value of the stream + * @param step the increment value of the stream + * @return the stream starting at value <code>start</code>. + */ + def from(start: Int, step: Int): Stream[Int] = + new Cons(start, from(start+step, step)) + + /** + * Create an infinite stream starting at <code>start</code> + * and incrementing by 1. + * + * @param start the start value of the stream + * @return the stream starting at value <code>start</code>. + */ + def from(start: Int): Stream[Int] = from(start, 1) + + /** + * Create an infinite stream containing the given element expression (which is computed for each + * occurrence) + * @param elem the element composing the resulting stream + * @return the stream containing an inifinite number of elem + * @deprecated use fill instead + */ + def fill[A](elem: => A): Stream[A] = new Cons(elem, fill(elem)) + + override def fill[A](n: Int)(elem: => A): Stream[A] = + if (n <= 0) Empty else new Cons(elem, fill(n-1)(elem)) + + override def tabulate[A](n: Int)(f: Int => A): Stream[A] = { + def loop(i: Int) = + if (i >= n) Empty else new Cons(f(i), tabulate(i+1)(f)) + loop(0) + } + + override def range(start: Int, end: Int, step: Int): Stream[Int] = + if (if (step < 0) start <= end else end <= start) Empty + else new Cons(start, range(start + step, end, step)) + + /** A stream containing all elements of a given iterator, in the order they are produced. + * @param it The iterator producing the stream's elements + * @deprecated use it.toStream instead + */ + @deprecated def fromIterator[A](it: Iterator[A]): Stream[A] = + if (it.hasNext) cons(it.next, fromIterator(it)) else empty + + /** The concatenation of a sequence of streams + * @deprecated use xs.flatten instead + */ + @deprecated def concat[A](xs: Iterable[Stream[A]]): Stream[A] = concat(xs.elements) + + /** The concatenation of all streams returned by an iterator + * @deprecated use xs.toStream.flatten instead + */ + @deprecated def concat[A](xs: Iterator[Stream[A]]): Stream[A] = + if (xs.hasNext) xs.next append concat(xs) + else empty + + /** + * Create a stream with element values + * <code>v<sub>n+1</sub> = step(v<sub>n</sub>)</code> + * where <code>v<sub>0</sub> = start</code> + * and elements are in the range between <code>start</code> (inclusive) + * and <code>end</code> (exclusive) + * @deprecated use @see iterate instead. + * @param start the start value of the stream + * @param end the end value of the stream + * @param step the increment function of the stream, must be monotonically increasing or decreasing + * @return the stream starting at value <code>start</code>. + */ + @deprecated def range(start: Int, end: Int, step: Int => Int): Stream[Int] = { + val up = step(start) > start + val down = step(start) < start + def loop(lo: Int): Stream[Int] = + if ((!up || lo < end) && (!down || lo > end)) cons(lo, loop(step(lo))) + else empty + loop(start) + } + + /** + * Create an infinite stream containing the given element. + * + * @param elem the element composing the resulting stream + * @return the stream containing an inifinite number of elem + * @deprecated use fill(elem) instead + */ + @deprecated def const[A](elem: A): Stream[A] = cons(elem, const(elem)) + + /** Create a stream containing several copies of an element. + * + * @param n the length of the resulting stream + * @param elem the element composing the resulting stream + * @return the stream composed of n elements all equal to elem + * @deprecated use fill(n, elem) instead + */ + @deprecated def make[A](n: Int, elem: A): Stream[A] = + const(elem) take n +} + + diff --git a/src/library/scala/collection/immutable/Traversible.scala b/src/library/scala/collection/immutable/Traversible.scala new file mode 100755 index 0000000000..5236f59681 --- /dev/null +++ b/src/library/scala/collection/immutable/Traversible.scala @@ -0,0 +1,24 @@ +package scala.collection.immutable + +import generic._ + +/** A subtrait of Traversible in package collection which represents traversibles + * that cannot be mutated. + * !!! todo: revise equality + * @author Matthias Zenger + * @autor Martin Odersky + * @version 2.8 + */ +trait Traversible[+A] extends collection.Traversible[A] with TraversibleTemplate[A, Traversible[A]] with Immutable { self => + override protected[this] def newBuilder = Traversible.newBuilder + override def traversibleBuilder[B]: Builder[B, Traversible[B], Any] = Traversible.newBuilder[B] +} + +/* A factory object for the trait `Traversible` */ +object Traversible extends TraversibleFactory[Traversible] { + type Coll = Traversible[_] + implicit def builderFactory[A]: BuilderFactory[A, Traversible[A], Coll] = new BuilderFactory[A, Traversible[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Traversible[A], Any] = new mutable.ListBuffer +} + + diff --git a/src/library/scala/collection/immutable/Tree.scala b/src/library/scala/collection/immutable/Tree.scala.disabled index cdf3ea61ba..538b2ccf9f 100644 --- a/src/library/scala/collection/immutable/Tree.scala +++ b/src/library/scala/collection/immutable/Tree.scala.disabled @@ -1,4 +1,4 @@ -/* __ *\ +o/* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** @@ -8,6 +8,8 @@ // $Id$ +// This is probably no longer needed; replaced by RedBlack.scala +* /* General Balanced Trees - highly efficient functional dictionaries. ** ** This is a scala version of gb_trees.erl which is @@ -20,7 +22,7 @@ ** ** NOTE: This code was until 2007-04-01 under a GPL license. The author has ** given permission to remove that license, so that now this code is under -** the general license for the Scala libraries. +** the general license for the Scala libraries. */ package scala.collection.immutable @@ -399,7 +401,7 @@ date Tue, Apr 29, 2008 at 3:31 PM subject Re: test mailed-by chara.epfl.ch signed-by gmail.com - + Hi Martin, I am fine with that change, and since I don't have a scala distribution handy, diff --git a/src/library/scala/collection/immutable/TreeHashMap.scala b/src/library/scala/collection/immutable/TreeHashMap.scala index 33915402ec..80a227b9ad 100644 --- a/src/library/scala/collection/immutable/TreeHashMap.scala +++ b/src/library/scala/collection/immutable/TreeHashMap.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2008-2009, David MacIver ** @@ -58,14 +59,16 @@ class TreeHashMap[Key, +Value] private (private val underlying : IntMap[AssocMap override lazy val size = underlying.values.foldLeft(0)((x, y) => x + y.size); + // todo: probably drop to make conform with general equals/hashcode policy override def equals(that : Any) = that match { case (that : TreeHashMap[_, _]) => if (this eq that) true else if (this.size != that.size) false; else this.underlying == that.underlying; - case _ => false; + case _ => false } + // todo: probably drop to make conform with general equals/hashcode policy override def hashCode = underlying.hashCode override def foreach(f : ((Key, Value)) => Unit) = underlying.foreachValue(_.foreach(f)); @@ -282,3 +285,4 @@ private[collection] class AssocMapIterator[Key, Value](var it : AssocMap[Key, Va } } +*/ diff --git a/src/library/scala/collection/immutable/TreeMap.scala b/src/library/scala/collection/immutable/TreeMap.scala index d915eba861..d679241b5c 100644 --- a/src/library/scala/collection/immutable/TreeMap.scala +++ b/src/library/scala/collection/immutable/TreeMap.scala @@ -12,15 +12,14 @@ package scala.collection.immutable +import generic._ /** The canonical factory of <a href="TreeMap.html">TreeMap</a>'s. */ object TreeMap { - /** The empty map of this type - * @deprecated use <code>empty</code> instead - */ - @deprecated - def Empty[A <% Ordered[A], B] = empty[A, B] + type Coll = TreeMap[_, _] + implicit def builderFactory[A <% Ordered[A], B]: BuilderFactory[(A, B), TreeMap[A, B], Coll] = new BuilderFactory[(A, B), TreeMap[A, B], Coll] { def apply(from: Coll) = newBuilder[A, B] } + def newBuilder[A <% Ordered[A], B]: Builder[(A, B), TreeMap[A, B], Any] = new ImmutableMapBuilder(empty[A, B]) /** The empty map of this type */ def empty[A <% Ordered[A], B] = new TreeMap[A, B] @@ -37,8 +36,14 @@ object TreeMap { * @version 1.1, 03/05/2004 */ @serializable -class TreeMap[A <% Ordered[A], +B](val size: Int, t: RedBlack[A]#Tree[B]) -extends RedBlack[A] with SortedMap[A, B] { +class TreeMap[A <% Ordered[A], +B](override val size: Int, t: RedBlack[A]#Tree[B]) + extends RedBlack[A] + with SortedMap[A, B] + with SortedMapTemplate[A, B, TreeMap[A, B]] + with ImmutableMapTemplate[A, B, TreeMap[A, B]] { + + override protected[this] def newBuilder : Builder[(A, B), TreeMap[A, B], Any] = + TreeMap.newBuilder[A, B] def isSmaller(x: A, y: A) = x < y @@ -46,22 +51,20 @@ extends RedBlack[A] with SortedMap[A, B] { protected val tree: RedBlack[A]#Tree[B] = if (size == 0) Empty else t - override def rangeImpl(from : Option[A], until : Option[A]) : SortedMap[A,B] = { + override def rangeImpl(from : Option[A], until : Option[A]): TreeMap[A,B] = { val ntree = tree.range(from,until) new TreeMap[A,B](ntree.count, ntree) } + override def firstKey = t.first override def lastKey = t.last override def compare(k0: A, k1: A): Int = k0.compare(k1) - - - private def newMap[B](s: Int, t: RedBlack[A]#Tree[B]) = new TreeMap[A, B](s, t) /** A factory to create empty maps of the same type of keys. */ - def empty[C] = TreeMap.empty[A, C] + override def empty = TreeMap.empty /** A new TreeMap with the entry added is returned, * if key is <em>not</em> in the TreeMap, otherwise @@ -71,11 +74,28 @@ extends RedBlack[A] with SortedMap[A, B] { * @param value ... * @return ... */ - def update [B1 >: B](key: A, value: B1): TreeMap[A, B1] = { + def add [B1 >: B](key: A, value: B1): TreeMap[A, B1] = { val newsize = if (tree.lookup(key).isEmpty) size + 1 else size newMap(newsize, tree.update(key, value)) } + /** Add a key/value pair to this map. + * @param kv the key/value pair + * @return A new map with the new binding added to this map + */ + override def + [B1 >: B] (kv: (A, B1)): TreeMap[A, B1] = add(kv._1, kv._2) + + /** Adds two or more elements to this collection and returns + * either the collection itself (if it is mutable), or a new collection + * with the added elements. + * + * @param elem1 the first element to add. + * @param elem2 the second element to add. + * @param elems the remaining elements to add. + */ + override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): TreeMap[A, B1] = + this + elem1 + elem2 ++ collection.Iterable.fromOld(elems) + /** A new TreeMap with the entry added is returned, * assuming that key is <em>not</em> in the TreeMap. */ @@ -99,37 +119,16 @@ extends RedBlack[A] with SortedMap[A, B] { case _ => None } - /** Retrieve the value which is associated with the given key. This - * method throws an exception if there is no mapping from the given - * key to a value. - * - * @param key the key - * @return the value associated with the given key. - * @throws Error("key not found"). - */ - override def apply(key: A): B = tree.lookup(key) match { - case n: NonEmpty[b] => n.value - case _ => super.apply(key) - } - /** Creates a new iterator over all elements contained in this * object. * * @return the new iterator */ - def elements: Iterator[Pair[A, B]] = tree.elements.elements - - override def foreach(f : Tuple2[A,B] => Unit) : Unit = - tree.visit[Unit](())((unit0,a,b) => Tuple2(true, f(Tuple2(a,b)))) - override def forall(f : Tuple2[A,B] => Boolean) : Boolean = - tree.visit[Boolean](true)((input,a,b) => f(Tuple2(a,b)) match { - case ret if input => Tuple2(ret,ret) - })._2 - override def exists(f : Tuple2[A,B] => Boolean) : Boolean = - tree.visit[Boolean](false)((input,a,b) => f(Tuple2(a,b)) match { - case ret if !input => Tuple2(!ret,ret) - })._2 + def elements: Iterator[(A, B)] = tree.toStream.elements + + override def toStream: Stream[(A, B)] = tree.toStream + override def foreach(f : ((A,B)) => Unit) = tree foreach { case (x, y) => f(x, y) } } diff --git a/src/library/scala/collection/immutable/TreeMap.scala.disabled b/src/library/scala/collection/immutable/TreeMap.scala.disabled deleted file mode 100644 index 0b3bb7a0e7..0000000000 --- a/src/library/scala/collection/immutable/TreeMap.scala.disabled +++ /dev/null @@ -1,101 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: TreeMap.scala 8997 2006-10-19 20:52:30Z odersky $ - -package scala.collection.immutable - - -object TreeMap { - def Empty[A <% Ordered[A], B] = new TreeMap[A, B] -} - -/** This class implements immutable maps using a tree. - * - * @author Erik Stenman - * @author Matthias Zenger - * @version 1.1, 03/05/2004 - */ - -[serializable] -class TreeMap[A <% Ordered[A], B] extends Tree[A, Pair[A, B]] with Map[A, B] { - - override protected type This = TreeMap[A, B] - override protected def getThis: This = this - - /** A factory to create empty maps of the same type of keys. - */ - def empty[C] = new TreeMap[A, C] - - /** Creates a new TreeMap from a GBTree and its size. - * - * @param sz ... - * @param t ... - * @return ... - */ - protected def New(sz: Int, t: aNode): This = new TreeMap[A, B] { - override def size = sz - override protected def tree: aNode = t - } - - /** A new TreeMap with the entry added is returned, - * if key is <em>not</em> in the TreeMap, otherwise - * the key is updated with the new entry. - * - * @param key ... - * @param value ... - * @return ... - */ - def update [B1 >: B](key: A, value: B1) = updateOrAdd(key, {key, value}) - - /** A new TreeMap with the entry added is returned, - * assuming that key is <em>not</em> in the TreeMap. - */ - def insert [B1 >: B](key:A, value:B) = add(key, {key, value}) - - /** Removes the key from the TreeMap. - */ - def remove(key:A) = deleteAny(key) - - /** Check if this map maps <code>key</code> to a value and return the - * value if it exists. - * - * @param key the key of the mapping of interest - * @return the value of the mapping, if it exists - */ - override def get(key: A): Option[B] = - findValue(key) match { - case Some(Pair(_, value)) => Some(value) - case _ => None - } - - /** Retrieve the value which is associated with the given key. This - * method throws an exception if there is no mapping from the given - * key to a value. - * - * @param key the key - * @return the value associated with the given key. - * @throws Error("key not found"). - */ - override def apply(key: A): B = tree.apply(key)._2 - - /** Creates a list of all (key, value) mappings. - * - * @return the list of all mappings - */ - override def toList: List[Pair[A, B]] = - tree.toList(scala.Nil) map (._2) - - /** Creates a new iterator over all elements contained in this - * object. - * - * @return the new iterator - */ - def elements: Iterator[Pair[A, B]] = entries -} - diff --git a/src/library/scala/collection/immutable/TreeSet.scala b/src/library/scala/collection/immutable/TreeSet.scala index 44e50c29a2..49c2578c29 100644 --- a/src/library/scala/collection/immutable/TreeSet.scala +++ b/src/library/scala/collection/immutable/TreeSet.scala @@ -11,17 +11,22 @@ package scala.collection.immutable -/** The canonical factory of <a href="TreeSet.html">TreeSet</a>'s. */ +import generic._ +/** The canonical factory of <a href="TreeSet.html">TreeSet</a>'s. */ object TreeSet { + type Coll = TreeSet[_] + implicit def implicitBuilder[A <% Ordered[A]]: Builder[A, TreeSet[A], Coll] = newBuilder[A] + def newBuilder[A <% Ordered[A]]: Builder[A, TreeSet[A], Any] = new AddingBuilder(empty[A]) + /** The empty set of this type */ def empty[A <% Ordered[A]] = new TreeSet[A] /** The canonical factory for this type */ - def apply[A <% Ordered[A]](elems: A*) : SortedSet[A] = empty[A] ++ elems + def apply[A <% Ordered[A]](elems: A*) : TreeSet[A] = empty[A] ++ elems } /** This class implements immutable sets using a tree. @@ -31,8 +36,8 @@ object TreeSet { */ @serializable -class TreeSet[A <% Ordered[A]](val size: Int, t: RedBlack[A]#Tree[Unit]) - extends RedBlack[A] with SortedSet[A] { +class TreeSet[A <% Ordered[A]](override val size: Int, t: RedBlack[A]#Tree[Unit]) + extends RedBlack[A] with SortedSet[A] with SortedSetTemplate[A, TreeSet[A]] { def isSmaller(x: A, y: A) = x < y @@ -42,9 +47,9 @@ class TreeSet[A <% Ordered[A]](val size: Int, t: RedBlack[A]#Tree[Unit]) private def newSet(s: Int, t: RedBlack[A]#Tree[Unit]) = new TreeSet[A](s, t) - /** A factory to create empty maps of the same type of keys. + /** A factory to create empty sets of the same type of keys. */ - def empty[B]: Set[B] = ListSet.empty[B] + override def empty = TreeSet.empty /** A new TreeSet with the entry added is returned, */ @@ -77,29 +82,17 @@ class TreeSet[A <% Ordered[A]](val size: Int, t: RedBlack[A]#Tree[Unit]) * * @return the new iterator */ - def elements: Iterator[A] = tree.elements.elements map (_._1) + def elements: Iterator[A] = tree.toStream.elements map (_._1) - def elementsSlow = tree.elementsSlow map (_._1) + override def toStream: Stream[A] = tree.toStream map (_._1) - override def foreach(f: A => Unit) { - tree.visit[Unit](())((unit0, y, unit1) => Tuple2(true, f(y))) - } + override def foreach(f: A => Unit) = tree foreach { (x, y) => f(x) } - override def forall(f: A => Boolean): Boolean = - tree.visit[Boolean](true)((input, a, unit) => f(a) match { - case ret if input => Tuple2(ret, ret) - })._2 - - override def exists(f: A => Boolean): Boolean = - tree.visit[Boolean](false)((input, a, unit) => f(a) match { - case ret if !input => Tuple2(!ret, ret) - })._2 - - override def rangeImpl(from: Option[A], until: Option[A]): TreeSet[A] = { - val tree = this.tree.range(from, until) - newSet(tree.count, tree) - } - override def firstKey = tree.first - override def lastKey = tree.last - override def compare(a0: A, a1: A) = a0.compare(a1) + override def rangeImpl(from: Option[A], until: Option[A]): TreeSet[A] = { + val tree = this.tree.range(from, until) + newSet(tree.count, tree) + } + override def firstKey = tree.first + override def lastKey = tree.last + override def compare(a0: A, a1: A) = a0.compare(a1) } diff --git a/src/library/scala/collection/immutable/UnbalancedTreeMap.scala b/src/library/scala/collection/immutable/UnbalancedTreeMap.scala deleted file mode 100644 index ab8822622b..0000000000 --- a/src/library/scala/collection/immutable/UnbalancedTreeMap.scala +++ /dev/null @@ -1,143 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -// todo: make balanced once Tree.scala is updated to be covariant. - -package scala.collection.immutable - - -object UnbalancedTreeMap { - - /** The empty map of this type */ - def empty[A <% Ordered[A], B] = new UnbalancedTreeMap[A, B] - - /** The canonical factory for this type - */ - def apply[A<% Ordered[A], B](elems: (A, B)*) = empty[A, B] ++ elems -} - -/** This class implements immutable maps using a tree. - * - * @author Martin Odersky - * @version 1.1, 02/01/2007 - */ - -@serializable -class UnbalancedTreeMap[A <% Ordered[A], +B] extends Map[A, B] { - - /** A factory to create empty maps of the same type of keys. - */ - def empty[C] = UnbalancedTreeMap.empty[A, C] - - def size: Int = 0 - - override def isEmpty: Boolean = true - - protected def add [B1 >: B](key: A, value: B1) = new Node(key, value, this, this) - protected def findValue (key: A): UnbalancedTreeMap[A, B] = this - - protected def key: A = throw new NoSuchElementException("empty map") - protected def value: B = throw new NoSuchElementException("empty map") - protected def smallest: UnbalancedTreeMap[A, B] = throw new NoSuchElementException("empty map") - - /** A new TreeMap with the entry added is returned, - * if key is <em>not</em> in the TreeMap, otherwise - * the key is updated with the new entry. - * - * @param key ... - * @param value ... - * @return ... - */ - def update[B1 >: B](key: A, value: B1) = add(key, value) - - /** A new TreeMap with the entry added is returned, - * assuming that key is <em>not</em> in the TreeMap. - */ - def insert[B1 >: B](key: A, value: B1) = add(key, value) - - def - (key:A): UnbalancedTreeMap[A, B] = this - - /** Check if this map maps <code>key</code> to a value and return the - * value if it exists. - * - * @param key the key of the mapping of interest - * @return the value of the mapping, if it exists - */ - override def get(key: A): Option[B] = { - val t = findValue(key) - if (t.isEmpty) None - else Some(t.value) - } - - /** Retrieve the value which is associated with the given key. This - * method throws an exception if there is no mapping from the given - * key to a value. - * - * @param key the key - * @return the value associated with the given key. - * @throws Error("key not found"). - */ - override def apply(key: A): B = { - val t = findValue(key) - if (!t.isEmpty) t.value - else super.apply(key) - } - - /** Creates a new iterator over all elements contained in this - * object. - * - * @return the new iterator - */ - def elements: Iterator[(A, B)] = Iterator.empty - - protected class Node[+B](override protected val key: A, - override protected val value: B, - left: UnbalancedTreeMap[A, B], - right: UnbalancedTreeMap[A, B]) extends UnbalancedTreeMap[A, B] - { - override def size = left.size + right.size + 1 - - override def isEmpty = false - - override protected def add [B1 >: B](k: A, v: B1) = - if (k < key) new Node[B1](key, value, left.add(k, v), right) - else if (k > key) new Node[B1](key, value, left, right.add(k, v)) - else new Node[B1](k, v, left, right) - - override protected def findValue (k: A): UnbalancedTreeMap[A, B] = - if (k < key) left.findValue(k) - else if (k > key) right.findValue(k) - else this - - override protected def smallest: UnbalancedTreeMap[A, B] = - if (left.isEmpty) this else left.smallest - - override def - (k: A): UnbalancedTreeMap[A, B] = - if (k < key) new Node(key, value, left - k, right) - else if (k > key) new Node(key, value, left, right - k) - else combine(left, right) - - private def combine[B](l: UnbalancedTreeMap[A, B], r: UnbalancedTreeMap[A, B]) = { - if (l.isEmpty) r - else if (r.isEmpty) l - else { - val s = r.smallest - new Node(s.key, s.value, l, r - s.key) - } - } - - override def elements: Iterator[(A, B)] = - left.elements append Iterator.single((key, value)) append right.elements - } -} - - - - diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala new file mode 100755 index 0000000000..7bb76c5518 --- /dev/null +++ b/src/library/scala/collection/immutable/Vector.scala @@ -0,0 +1,29 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.collection.immutable + +import generic._ +import mutable.ArrayBuffer + +/** A subtrait of collection.Vector which represents sequences + * that cannot be mutated. + */ +trait Vector[+A] extends Sequence[A] with collection.Vector[A] with VectorTemplate[A, Vector[A]] { self => + override protected[this] def newBuilder = Vector.newBuilder + override def traversibleBuilder[B]: Builder[B, Vector[B], Any] = Vector.newBuilder[B] +} + +object Vector extends SequenceFactory[Vector] { + type Coll = Vector[_] + class Impl[A](buf: ArrayBuffer[A]) extends Vector[A] { // todo: insert better vector implementation here + def length = buf.length + def apply(idx: Int) = buf.apply(idx) + } + implicit def builderFactory[A]: BuilderFactory[A, Vector[A], Coll] = new BuilderFactory[A, Vector[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Vector[A], Any] = new ArrayBuffer[A] mapResult (buf => new Impl(buf)) +} diff --git a/src/library/scala/collection/jcl/ArrayList.scala b/src/library/scala/collection/jcl/ArrayList.scala deleted file mode 100644 index 90eaa93050..0000000000 --- a/src/library/scala/collection/jcl/ArrayList.scala +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Creates a buffer backed by a Java array list. - * - * @author Sean McDirmid - */ -class ArrayList[A](override val underlying : java.util.ArrayList[A]) extends BufferWrapper[A] { - def this() = this(new java.util.ArrayList[A]); - override def clone: ArrayList[A] = - new ArrayList[A](underlying.clone().asInstanceOf[java.util.ArrayList[A]]) -} diff --git a/src/library/scala/collection/jcl/Buffer.scala b/src/library/scala/collection/jcl/Buffer.scala deleted file mode 100644 index 5f6d898db1..0000000000 --- a/src/library/scala/collection/jcl/Buffer.scala +++ /dev/null @@ -1,229 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** A mutable sequence that supports element insertion and update. - * - * @author Sean McDirmid - */ -trait Buffer[A] extends RandomAccessSeq.Mutable[A] with Ranged[Int,A] with MutableSeq[A] with Collection[A] { - final protected type SortedSelf = Buffer[A]; - - override def projection : Buffer.Projection[A] = new Buffer.Projection[A] { - override def elements = Buffer.this.elements - override def length = Buffer.this.length - override def apply(idx : Int) = Buffer.this.apply(idx) - override def transform(f : A => A) = Buffer.this.transform(f) - } - - protected class DefaultBufferIterator extends DefaultSeqIterator with BufferIterator[Int,A] { - override def set(a : A) = { - if (index == 0) throw new NoSuchElementException - Buffer.this.set(index - 1, a) - } - override def add(a : A) = { - Buffer.this.add(index, a) - } - } - override def elements : BufferIterator[Int,A] = new DefaultBufferIterator - - /** The first index of a buffer is 0. */ - override def firstKey = 0; - - /** The last index of a buffer is its size - 1. */ - override def lastKey = size - 1; - - /** Indices are compared through subtraction. */ - final def compare(k0 : Int, k1 : Int) = k0 - k1; - - /** Removes the element at index <code>idx</code> */ - def remove(idx : Int) = { - val i = elements; - val ret = i.seek(idx); i.remove; ret; - } - /** Removes N elements from index <code>idx</code> */ - def remove(idx : Int, length : Int) = { - val i = elements - i.seek(idx) - for (j <- 0.until(length)) i.remove - } - /** replaces */ - def replace(from : Int, length : Int, added : Seq[A]) = { - val min = if (length < added.length) length else added.length - val i = added.elements - var j = 0 - while (j < length && i.hasNext) { - set(from + j, i.next); j = j + 1 - } - assert(j == min) - if (i.hasNext) { - val slice = added.drop(length) - assert(!slice.isEmpty) - addAll(from + min, slice) - } else if (j < length) { - assert(length > min) - remove(from + min, length - min) - } - } - - /** Replaces the element at index "idx" with "a." - * @returns the element replaced. - */ - def set(idx : Int, a : A) : A = { - val i = elements; - val ret = i.seek(idx); i.set(a); ret; - } - - /** Equivalent to set except the replaced element is not returned. */ - def update(idx : Int, a : A) : Unit = set(idx, a); - - /** @returns always true. */ - def add(a : A) : Boolean = { - val i = elements; - while (i.hasNext) i.next; - i.add(a); - true; - } - - /** Inserts "a" into this buffer just before the element at index "idx." */ - def add(idx: Int, a: A): Unit = { - val i = elements; i.seek(idx); - i.add(a); - } - - /** Inserts all elements of <code>that</code> into this buffer just before - * the element at index <code>idx</code>. - * - * @param idx .. - * @param that .. - */ - def addAll(idx: Int, that: Iterable[A]): Unit = { - val i = elements; i.seek(idx); - for (that <- that) { - i.add(that); i.next; - } - } - - override def transform(f: A => A): Boolean = { - var changed = false; - val i = elements; - while (i.hasNext) { - val a0 = i.next; - val a1 = f(a0); - if (a0 != a1) { - i.set(a1); changed = true; - } - } - changed; - } - override def +(a : A) : this.type = super[Collection].+(a); - override def -=(a : A) = super[Collection].-=(a); - override def isEmpty = super[MutableSeq].isEmpty; - override def rangeImpl(from : Option[Int], until : Option[Int]) : Buffer[A] = new Range(from, until); - - - protected class Range(var from : Option[Int], var until : Option[Int]) extends Buffer[A] { - if (from == None && until == None) throw new IllegalArgumentException; - if (from != None && until != None && !(from.get < until.get)) throw new IllegalArgumentException; - override def add(a : A) = - if (until == None) Buffer.this.add(a); - else { - Buffer.this.add(until.get, a); - true; - } - private def translate(idx : Int) = { - if (until != None && idx > until.get) throw new IllegalArgumentException; - else if (from != None) from.get + idx; - else idx; - } - override def apply(idx : Int) : A = Buffer.this.apply(translate(idx)); - override def set(idx : Int, a : A) = Buffer.this.set(translate(idx), a); - override def add(idx : Int, a : A) = Buffer.this.add(translate(idx), a); - override def remove(idx : Int) = Buffer.this.remove(translate(idx)); - override def length = { - if (until != None) { - if (from != None) until.get - from.get; - else until.get; - } else super.length; - } - override def elements : BufferIterator[Int,A] = new RangeIterator; - class RangeIterator extends BufferIterator[Int,A] { - val underlying = Buffer.this.elements; - if (from != None) underlying.seek(from.get); - def hasNext = underlying.hasNext && - (until == None || underlying.nextIndex < until.get); - def hasPrevious = underlying.hasPrevious && - (from == None || underlying.previousIndex >= from.get); - def next = { - if (until != None && underlying.nextIndex >= until.get) throw new NoSuchElementException; - underlying.next; - } - def previous = { - if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; - underlying.previous; - } - def add(a : A) = { - if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException; - if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; - underlying.add(a); - if (until != None) until = Some(until.get + 1); - } - def set(a : A) = { - if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException; - if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; - underlying.set(a); - } - def remove = { - if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException; - if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; - underlying.remove; - } - def nextIndex = { - val ret = underlying.nextIndex; - if (until != None && ret >= until.get) throw new NoSuchElementException; - if (from != None) ret - from.get; - else ret; - } - def previousIndex = { - val ret = underlying.previousIndex; - if (from != None && ret < from.get) throw new NoSuchElementException; - if (from != None) ret - from.get; - else ret; - } - } - } - /* - protected class Map[B](f : A => B) extends super.Map[B](f) with Buffer.Projection[B] { - override def elements = Buffer.this.elements.map[B](f); - //override def apply(idx : Int) = f(MutableSeq.this.apply(idx)); - //override def size = length; - } - */ -} -object Buffer { - def apply[T](list : java.util.List[T]) = new BufferWrapper[T] { - val underlying = list - } - - trait Projection0[A] extends MutableSeq.Projection[A] with RandomAccessSeq.Projection[A] { - override def projection : Projection0[A] = this - override def elements : SeqIterator[Int,A] = new DefaultSeqIterator - - protected class MapProjection[B](f : A => B) extends super.MapProjection[B](f) with Projection0[B] { - override def projection = this - } - override def map[B](f: A => B) : Projection0[B] = new MapProjection[B](f) - } - class Projection[A] extends Collection.Projection[A] with RandomAccessSeq.MutableProjection[A] with Projection0[A] with Buffer[A] { - override def elements : BufferIterator[Int,A] = new DefaultBufferIterator - override def projection : Buffer.Projection[A] = this - } -} diff --git a/src/library/scala/collection/jcl/BufferIterator.scala b/src/library/scala/collection/jcl/BufferIterator.scala deleted file mode 100644 index d9e07d0e23..0000000000 --- a/src/library/scala/collection/jcl/BufferIterator.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** An iterator for a buffer that supports element update and insertion. - * - * @author Sean McDirmid - */ -trait BufferIterator[K,A] extends SeqIterator[K,A] { - - /** Sets the element before this iterator's cursor to "a." - * Replaces either the last element returned by "next" or, - * if previous was called, - * the next element that would be return by "previous." - */ - def set(a: A): Unit; - - /** Inserts "a" after the iterator's cursor. - * If next was last called, "a" is inserted after the element returned. - * If previous was last called, "a" is inserted before the element returned. - */ - def add(a: A): Unit; -} diff --git a/src/library/scala/collection/jcl/BufferWrapper.scala b/src/library/scala/collection/jcl/BufferWrapper.scala deleted file mode 100644 index c422bb6448..0000000000 --- a/src/library/scala/collection/jcl/BufferWrapper.scala +++ /dev/null @@ -1,52 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Wraps Java lists. - * - * @author Sean McDirmid - */ -trait BufferWrapper[A] extends Buffer[A] with CollectionWrapper[A] { - def underlying : java.util.List[A]; - override def elements : BufferIterator[Int,A] = new IteratorWrapper(underlying.listIterator); - override def remove(idx : Int) = underlying.remove(idx).asInstanceOf[A]; - override def add(a : A) = underlying.add(a); - override def add(idx : Int, a : A) = underlying.add(idx,a); - override def addAll(idx : Int, that : Iterable[A]) = that match { - case that : CollectionWrapper[_] => underlying.addAll(idx, that.underlying); {} - case _ => super.addAll(idx, that); - } - override def indexOf(a : A) = { - val result = underlying.indexOf(a); - if (result == -1) None; - else Some(result); - } - override def apply(idx : Int) = underlying.get(idx).asInstanceOf[A]; - override def set(idx : Int, a : A) = underlying.set(idx, a).asInstanceOf[A]; - override def rangeImpl(from : Option[Int], until : Option[Int]) : Buffer[A] = new Range(from, until); - protected class Range(from : Option[Int], until : Option[Int]) extends super.Range(from,until) with BufferWrapper[A] { - val underlying = { - val fromi = if (from == None) 0 else from.get; - val toi = if (until == None) BufferWrapper.this.size else until.get; - BufferWrapper.this.underlying.subList(fromi, toi); - } - override def elements = super[BufferWrapper].elements; - } - class IteratorWrapper(underlying : java.util.ListIterator[A]) extends MutableIterator.Wrapper[A](underlying) with BufferIterator[Int,A] { - def add(a : A) = underlying.add(a); - def set(a : A) = underlying.set(a); - def hasPrevious = underlying.hasPrevious; - def previous = underlying.previous.asInstanceOf[A]; - def previousIndex = underlying.previousIndex; - def nextIndex = underlying.nextIndex; - } - override def length = underlying.size; -} diff --git a/src/library/scala/collection/jcl/Collection.scala b/src/library/scala/collection/jcl/Collection.scala deleted file mode 100644 index 670899f358..0000000000 --- a/src/library/scala/collection/jcl/Collection.scala +++ /dev/null @@ -1,67 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -object Collection { - val DEFAULT_FILTER : Any => Boolean = x => true; - trait Projection[A] extends Collection[A] with MutableIterable.Projection[A] { - override def projection = this - } -} - -/** Analogous to a Java collection. - * - * @author Sean McDirmid - */ -trait Collection[A] extends MutableIterable[A] { - /** Type-safe version of containsAll. - ** - ** @author Sean McDirmid - **/ - def hasAll(i: Iterable[A]): Boolean = i.forall(elements.has); - - /** Adds "a" to the collection, return true if "a" is actually added. */ - def add(a: A): Boolean; - - /** Adds all elements in "i" to the collection, return true if any elements are added. */ - def addAll(i: Iterable[A]): Boolean = { - var changed = false; - i.foreach(t => changed = add(t) || changed); - changed; - } - /** Operator shortcut for addAll. */ - def ++(that: Iterable[A]): this.type = { - addAll(that); this; - } - - /** removes "a" from the collection. */ - def -=(a : A) : Unit = remove(a); - - /** adds "a" from the collection. */ - def +=(t : A) : Unit = add(t); - - /** adds "a" from the collection. Useful for chaining. */ - def +(t : A) : this.type = { add(t); this; } - - /** Transforms each element of the collection in-place according to - * <code>f</code>. - * - * @param f - * @return <code>true</code> if the collection is actually updated. - */ - def transform(f: A => A): Boolean - override def projection : Collection.Projection[A] = new Collection.Projection[A] { - override def elements = Collection.this.elements - override def size = Collection.this.size - override def add(a: A): Boolean = Collection.this.add(a) - override def transform(f : A => A) = Collection.this.transform(f); - } -} diff --git a/src/library/scala/collection/jcl/CollectionWrapper.scala b/src/library/scala/collection/jcl/CollectionWrapper.scala deleted file mode 100644 index 028dbee8d4..0000000000 --- a/src/library/scala/collection/jcl/CollectionWrapper.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Used to wrap Java collections in Scala. - * - * @author Sean McDirmid - */ -trait CollectionWrapper[A] extends Collection[A] with IterableWrapper[A] { - /** Override to specify the collection being accessed through this wrapper. - ** Collection operations are then routed through the wrapped Java collection. - **/ - def underlying : java.util.Collection[A]; - override def has(a : A) = underlying.contains(a); - override def elements : MutableIterator[A] = super.elements; - override def size = underlying.size; - - override def hasAll(that : Iterable[A]) = that match { - case that : CollectionWrapper[_] => - val u = underlying; - u.containsAll(that.underlying); - case _ => super.hasAll(that); - } - override def add(a : A) = underlying.add(a); - override def addAll(that : Iterable[A]) = that match { - case that : CollectionWrapper[_] => underlying.addAll(that.underlying); - case _ => super.addAll(that); - } - override def toString = underlying.toString; - override def hashCode = underlying.hashCode; - override def equals(that : Any) = that match { - case that: CollectionWrapper[_] => underlying == that.underlying; - case _ => super.equals(that); - } -} diff --git a/src/library/scala/collection/jcl/Conversions.scala b/src/library/scala/collection/jcl/Conversions.scala deleted file mode 100644 index edb96322b6..0000000000 --- a/src/library/scala/collection/jcl/Conversions.scala +++ /dev/null @@ -1,17 +0,0 @@ -package scala.collection.jcl - -object Conversions { - implicit def convertSet[T](set : java.util.Set[T]) = Set(set) - implicit def convertList[T](set : java.util.List[T]) = Buffer(set) - implicit def convertSortedSet[T](set : java.util.SortedSet[T]) = SortedSet(set) - implicit def convertMap[T,E](set : java.util.Map[T,E]) = Map(set) - implicit def convertSortedMap[T,E](set : java.util.SortedMap[T,E]) = SortedMap(set) - - implicit def unconvertSet[T](set : SetWrapper[T]) = set.underlying - implicit def unconvertCollection[T](set : CollectionWrapper[T]) = set.underlying - implicit def unconvertList[T](set : BufferWrapper[T]) = set.underlying - implicit def unconvertSortedSet[T](set : SortedSetWrapper[T]) = set.underlying - implicit def unconvertMap[T,E](set : MapWrapper[T,E]) = set.underlying - implicit def unconvertSortedMap[T,E](set : SortedMapWrapper[T,E]) = set.underlying - -}
\ No newline at end of file diff --git a/src/library/scala/collection/jcl/HashMap.scala b/src/library/scala/collection/jcl/HashMap.scala deleted file mode 100644 index 050da57cff..0000000000 --- a/src/library/scala/collection/jcl/HashMap.scala +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A map that is backed by a Java hash map. - * - * @author Sean McDirmid - */ -class HashMap[K, E](override val underlying: java.util.HashMap[K, E]) extends MapWrapper[K, E] { - def this() = this(new java.util.HashMap[K, E]) - override def clone: HashMap[K, E] = - new HashMap[K, E](underlying.clone().asInstanceOf[java.util.HashMap[K, E]]) -} diff --git a/src/library/scala/collection/jcl/Hashtable.scala b/src/library/scala/collection/jcl/Hashtable.scala deleted file mode 100644 index 474a3740e4..0000000000 --- a/src/library/scala/collection/jcl/Hashtable.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A hash set that is backed by a Java hash table. - * - * @author Sean McDirmid - */ -class Hashtable[K,E](override val underlying: java.util.Hashtable[K,E]) extends MapWrapper[K,E] { - def this() = this(new java.util.Hashtable[K,E]) - - override def clone() : Hashtable[K,E] = - new Hashtable[K,E](underlying.clone().asInstanceOf[java.util.Hashtable[K,E]]) -} diff --git a/src/library/scala/collection/jcl/IdentityHashMap.scala b/src/library/scala/collection/jcl/IdentityHashMap.scala deleted file mode 100644 index d8ee237777..0000000000 --- a/src/library/scala/collection/jcl/IdentityHashMap.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A map that is backed by a Java identity hash map, which compares keys - * by their reference-based identity as opposed to using equals and hashCode. - * An identity hash map will often perform better than traditional hash map - * because it can utilize linear probing. - * - * @author Sean McDirmid - */ -class IdentityHashMap[K, E](override val underlying : java.util.IdentityHashMap[K, E]) extends MapWrapper[K, E] { - def this() = this(new java.util.IdentityHashMap[K, E]) - override def clone: IdentityHashMap[K, E] = - new IdentityHashMap[K, E](underlying.clone().asInstanceOf[java.util.IdentityHashMap[K, E]]) -} diff --git a/src/library/scala/collection/jcl/IterableWrapper.scala b/src/library/scala/collection/jcl/IterableWrapper.scala deleted file mode 100644 index 0836350ee3..0000000000 --- a/src/library/scala/collection/jcl/IterableWrapper.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** A wrapper around a Java collection that only supports remove mutations. - * - * @author Sean McDirmid - */ -trait IterableWrapper[A] extends MutableIterable[A] { - def underlying: java.util.Collection[A]; - override def remove(a: A) = underlying.remove(a); - override def removeAll(that: Iterable[A]) = that match { - case that: IterableWrapper[_] => underlying.removeAll(that.underlying); - case _ => super.removeAll(that); - } - override def retainAll(that : Iterable[A]) = that match { - case that : IterableWrapper[_] => underlying.retainAll(that.underlying); - case _ => super.retainAll(that); - } - override def size = underlying.size; - override def isEmpty = underlying.isEmpty; - override def clear = underlying.clear; - override def elements : MutableIterator[A] = new MutableIterator.Wrapper[A](underlying.iterator); -} diff --git a/src/library/scala/collection/jcl/LinkedHashMap.scala b/src/library/scala/collection/jcl/LinkedHashMap.scala deleted file mode 100644 index 039e88ca1c..0000000000 --- a/src/library/scala/collection/jcl/LinkedHashMap.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A map that is backed by a Java linked hash map, which fixes iteration - * order in terms of insertion order. - * - * @author Sean McDirmid - */ -class LinkedHashMap[K, E](override val underlying: java.util.LinkedHashMap[K, E]) extends MapWrapper[K, E] { - def this() = this(new java.util.LinkedHashMap[K, E]) - override def clone: LinkedHashMap[K, E] = - new LinkedHashMap[K, E](underlying.clone().asInstanceOf[java.util.LinkedHashMap[K, E]]) -} diff --git a/src/library/scala/collection/jcl/LinkedHashSet.scala b/src/library/scala/collection/jcl/LinkedHashSet.scala deleted file mode 100644 index 272c1dd267..0000000000 --- a/src/library/scala/collection/jcl/LinkedHashSet.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A set that is backed by a Java linked hash set, which fixes iteration - * order in terms of insertion order. - * - * @author Sean McDirmid - */ -class LinkedHashSet[A](override val underlying: java.util.LinkedHashSet[A]) extends SetWrapper[A] { - def this() = this(new java.util.LinkedHashSet[A]) - override def clone: LinkedHashSet[A] = - new LinkedHashSet[A](underlying.clone().asInstanceOf[java.util.LinkedHashSet[A]]) -} diff --git a/src/library/scala/collection/jcl/LinkedList.scala b/src/library/scala/collection/jcl/LinkedList.scala deleted file mode 100644 index 7b7c8cde2c..0000000000 --- a/src/library/scala/collection/jcl/LinkedList.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Creates a buffer backed by a Java linked list. Includes additional - * peek/poll/removeFirst/removeLast APIs that are useful in implementing - * queues and stacks. - * - * @author Sean McDirmid - */ -class LinkedList[A](override val underlying : java.util.LinkedList[A]) extends BufferWrapper[A] { - def this() = this(new java.util.LinkedList[A]); - override def elements = super[BufferWrapper].elements; - override def add(idx : Int, a : A) = - if (idx == 0) underlying.addFirst(a); - else super.add(idx, a); - //def peek = underlying.peek.asInstanceOf[A]; - //def poll = underlying.poll.asInstanceOf[A]; - //def removeFirst = underlying.removeFirst.asInstanceOf[A]; - //def removeLast = underlying.removeLast.asInstanceOf[A]; - - override def clone: LinkedList[A] = - new LinkedList[A](underlying.clone().asInstanceOf[java.util.LinkedList[A]]) -} diff --git a/src/library/scala/collection/jcl/Map.scala b/src/library/scala/collection/jcl/Map.scala deleted file mode 100644 index 22124eabb3..0000000000 --- a/src/library/scala/collection/jcl/Map.scala +++ /dev/null @@ -1,129 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** A mutable map that is compatible with Java maps. - * - * @author Sean McDirmid - */ -trait Map[K,E] extends MutableIterable[Tuple2[K,E]] with scala.collection.mutable.Map[K,E] { - override def clear() = super[MutableIterable].clear; - override def isEmpty = super[MutableIterable].isEmpty; - override def keySet : Set[K] = new KeySet; - override final def keys = keySet.elements; - /** The values of this map as a projection, which means - removals from the returned collection will remove the element from this map. - @returns a projection of this map's elements. */ - def valueSet : MutableIterable.Projection[E] = projection.map(_._2); - - override def put(key : K, elem : E) : Option[E] = throw new java.lang.AbstractMethodError - - override def ++=(that : Iterable[(K,E)]) : Unit = - that.foreach(p => put(p._1, p._2)); - - override def removeKey(key : K) : Option[E] = { - val i = elements; - while (!i.hasNext) { - val result = i.next; - if (result._1 == key) { - i.remove; - return Some(result._2); - } - } - return None; - } - override def has(pair : Tuple2[K,E]) = get(pair._1) match { - case Some(e) if e == pair._2 => true; - case _ => false; - } - override def get(key : K) = elements.find(p => p._1 == key).map(_._2); - override def update(key : K, e : E) : Unit = put(key,e); - override def +(pair : Tuple2[K,E]) : this.type = { - put(pair._1,pair._2); this; - } - override def +=(pair : Tuple2[K,E]) : Unit = put(pair._1, pair._2); - override def -(key : K) : this.type = { - removeKey(key); this; - } - override def remove(p : (K,E)) = get(p._1) match { - case Some(p._2) => this -= p._1; true - case _ => false; - } - - override def -=(key : K) : Unit = removeKey(key); - override def elements : MutableIterator[Tuple2[K,E]]; - - override def projection : Map.Projection[K,E] = new Map.Projection[K,E] { - override def elements = Map.this.elements - override def size = Map.this.size - override def get(k : K) = Map.this.get(k) - override def put(k : K, e : E) = Map.this.put(k, e) - } - /** - */ - def lense[F](f : E => F, g : F => E) : jcl.Map.Projection[K,F] = new Lense[F](f,g); - - protected class Lense[F](f : E => F, g : F => E) extends jcl.Map.Projection[K,F] { - override def elements = Map.this.elements.map(k => Tuple2(k._1, f(k._2))); - override def removeKey(key : K) = Map.this.removeKey(key).map(f); - override def put(key : K, elem : F) = Map.this.put(key, g(elem)).map(f); - override def get(key : K) = Map.this.get(key).map(f); - override def lense[G](f0 : F => G, g0 : G => F) : jcl.Map.Projection[K,G] = - Map.this.lense[G](x => f0(f(x)), y => g(g0(y))); - override def size = size0; - } - protected class KeySet extends Set[K] { - override def size = Map.this.size; - override def add(k : K) = Map.this.put(k, default(k)) == None; - override def elements = Map.this.elements.map(_._1); - override def has(k : K) = Map.this.contains(k); - } - override def filterKeys(p : K => Boolean) : Map.Projection[K,E] = new Filter(p); - - protected class Filter(p : K => Boolean) extends Map.Projection[K,E] { - override def elements = { - val i = Map.this.elements.filter(e => p(e._1)); - new MutableIterator[(K,E)] { - def next = i.next - def hasNext = i.hasNext - def remove : Unit = throw new NoSuchMethodException - } - } - override def removeKey(key : K) = { - if (!p(key)) throw new IllegalArgumentException; - Map.this.removeKey(key); - } - override def contains(key : K) = p(key) && Map.this.contains(key); - override def put(key : K, elem : E) = { - if (!p(key)) throw new IllegalArgumentException; - Map.this.put(key, elem); - } - override def get(key : K) = { - if (!p(key)) None; - else Map.this.get(key); - } - override def filterKeys(p0 : K => Boolean) : Map.Projection[K,E] = - Map.this.filterKeys(e => p(e) && p0(e)); - - override def size = size0; - } -} - -object Map { - trait MutableIterableProjection[A] extends MutableIterable.Projection[A]; - trait Projection[K,E] extends MutableIterableProjection[(K,E)] with scala.collection.Map.Projection[K,E] with Map[K,E] { - override def projection = this - override def map[B](f : ((K,E)) => B) : MutableIterable.Projection[B] = super[MutableIterableProjection].map(f); - } - def apply[T,E](map0 : java.util.Map[T,E]) = new MapWrapper[T,E] { - val underlying = map0 - } -} diff --git a/src/library/scala/collection/jcl/MapWrapper.scala b/src/library/scala/collection/jcl/MapWrapper.scala deleted file mode 100644 index e8b39e8886..0000000000 --- a/src/library/scala/collection/jcl/MapWrapper.scala +++ /dev/null @@ -1,76 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A wrapper around a Java map. - * - * @author Sean McDirmid - */ -trait MapWrapper[K, E] extends jcl.Map[K, E] { - def underlying: java.util.Map[K, E] - override def size = underlying.size - override def isEmpty = underlying.isEmpty - override def clear() = underlying.clear - - override def put(key: K, elem: E) = { - //if (elem == null) throw new IllegalArgumentException; - val ret = underlying.put(key, elem) - if (ret == null) None else Some(ret.asInstanceOf[E]) - } - - override def get(key : K) : Option[E] = { - val ret = underlying.get(key); - if (ret == null) None else Some(ret.asInstanceOf[E]); - } - - override def ++=(that : Iterable[Tuple2[K,E]]) : Unit = that match { - case that : MapWrapper[_,_] => underlying.putAll(that.underlying); - case _ => super.++=(that) - } - - override def removeKey(key: K) = { - val ret = underlying.remove(key) - if (ret == null) None else Some(ret.asInstanceOf[E]) - } - - override def contains(key: K) = underlying.containsKey(key) - override def keySet: Set.Projection[K] = new KeySet - override def valueSet: MutableIterable.Projection[E] = new ValueSet - override def elements: MutableIterator[Tuple2[K,E]] = new IteratorWrapper - - class IteratorWrapper extends MutableIterator[Tuple2[K,E]] { - val underlying = MapWrapper.this.underlying.entrySet.iterator - def hasNext = underlying.hasNext - def remove = underlying.remove - def next = { - val next = underlying.next.asInstanceOf[java.util.Map.Entry[K,E]] - Tuple2(next.getKey.asInstanceOf[K],next.getValue.asInstanceOf[E]) - } - } - - class KeySet extends super.KeySet with SetWrapper[K] with Set.Projection[K] { - val underlying = MapWrapper.this.underlying.keySet - } - - class ValueSet extends IterableWrapper[E] with MutableIterable.Projection[E] { - override def size = MapWrapper.this.size - val underlying = MapWrapper.this.underlying.values - override def has(e : E) = MapWrapper.this.underlying.containsValue(e) - } - - override def toString = underlying.toString - override def hashCode = underlying.hashCode - - override def equals(that : Any) = that match { - case that: MapWrapper[_,_] => underlying == that.underlying - case _ => super.equals(that) - } -} diff --git a/src/library/scala/collection/jcl/MutableIterable.scala b/src/library/scala/collection/jcl/MutableIterable.scala deleted file mode 100644 index 9a7d078d29..0000000000 --- a/src/library/scala/collection/jcl/MutableIterable.scala +++ /dev/null @@ -1,110 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** - * An iterable collection that supports remove operations. - * Useful for representing projections of mutable collections that where only - * the remove operation makes sense. - * - * @author Sean McDirmid - */ -trait MutableIterable[A] extends scala.Collection[A] { - /** @return true if t is in the collection. - **/ - def has(t : A ) : Boolean = elements.contains(t); - - /** @return true if t was removed from this collection. - **/ - def remove(t : A ) : Boolean = elements.remove(t); - /** @return true if any element in that was removed from this collection. - **/ - def removeAll(that : Iterable[A]) : Boolean = { - var changed = false; - that.foreach(t => changed = elements.remove(t) || changed); - changed; - } - /** Operator shortcut for removeAll. */ - def --(that : Iterable[A]) : this.type = { - removeAll(that); this; - } - - /** @return the collection that t was removed from. - */ - def -(t : A) : this.type = { remove(t); this; } - /** retain only elements in the collection that predicate p is true for. - */ - def retainOnly(p : A => Boolean) : Unit = elements.retain(p); - /** retain only elements that are also in that. - */ - def retainAll(that : Iterable[A]) : Boolean = elements.retain(s => that.exists(t => t == s)); - - /** @return the current number of elements in the collection. - */ - protected def size0 : Int = { - var count = 0; - val i = elements; - while (i.hasNext) { count = count + 1; i.next; } - count; - } - - /** clear all elements from the collection. - */ - def clear(): Unit = { - val i = elements; - while (i.hasNext) { - i.next; i.remove; - } - } - override def projection : MutableIterable.Projection[A] = new MutableIterable.Projection[A] { - override def elements = MutableIterable.this.elements - override def size = MutableIterable.this.size - override def remove(t : A ) : Boolean = MutableIterable.this.remove(t) - override def filter(p : A => Boolean) : MutableIterable.Projection[A] = super.filter(p) - } - /** The default implementation of a map over mutable iterable collections. - **/ - override def elements : MutableIterator[A]; - protected class Map[B](f : A => B) extends MutableIterable.Projection[B] { - override def elements = MutableIterable.this.elements.map(f) - override def size = MutableIterable.this.size - } - trait Filter extends MutableIterable.Projection[A] { - protected def p(a : A) : Boolean - override def has(a : A) = if (!p(a)) false else MutableIterable.this.has(a); - override def remove(a : A) = { - if (!p(a)) throw new IllegalArgumentException; - MutableIterable.this.remove(a); - } - override def filter(p0 : A => Boolean) : MutableIterable.Projection[A] = - MutableIterable.this.projection.filter(a => p(a) && p0(a)); - def elements = { - val i = MutableIterable.this.elements.filter(p); - new MutableIterator[A] { - def next = i.next - def hasNext = i.hasNext - def remove : Unit = throw new NoSuchMethodException - } - } - def size = size0; - } -} - -object MutableIterable { - trait Projection[A] extends MutableIterable[A] with Iterable.Projection[A] { - override def projection = this - override def map[B](f : A => B) : Projection[B] = new Map[B](f); - override def filter(pp : A => Boolean) : Projection[A] = new Filter { - def p(a : A) = pp(a) - } - } -} - diff --git a/src/library/scala/collection/jcl/MutableIterator.scala b/src/library/scala/collection/jcl/MutableIterator.scala deleted file mode 100644 index 0170939712..0000000000 --- a/src/library/scala/collection/jcl/MutableIterator.scala +++ /dev/null @@ -1,70 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -object MutableIterator { - class Wrapper[A](val underlying : java.util.Iterator[A]) extends MutableIterator[A] { - def hasNext = underlying.hasNext; - def next = underlying.next.asInstanceOf[A]; - def remove = underlying.remove; - } -} - -/** An iterator that supports the remove operation. - * These iterators wrap Java iterators, and so have the same fail fast - * behavior when dealing with concurrent modifications. - * - * @author Sean McDirmid - */ -trait MutableIterator[A] extends Iterator[A] { - def remove : Unit; - - /* filter doesnt' support remove yet. - override def filter(f : A => Boolean) : MutableIterator[A] = { - val buffered = this.buffered0; - new buffered.Filter(f); - } - */ - - override def map[B](f: A => B) : MutableIterator[B] = new Map(f); - /** A type-safe version of contains. - **/ - def has(a: A) = exists(b => a == a); - - /** Finds and removes the first instance of "a" through the iterator. - * After execution, the iterator's cursor is located where the removed - * element existed. - * - * @param a .. - * @return <code>false</code> if "a" is not encountered in the iterator - * and the iterator's cursor is located at the end of its elements. - */ - def remove(a: A): Boolean = { - while (hasNext) - if (next == a) { remove; return true; } - return false; - } - /** Removes all elements in the iterator that predicate "p" returns false on. - **/ - def retain(p : A => Boolean) : Boolean = { - var changed = false; - while (hasNext) - if (!p(next)) { remove; changed = true; } - changed; - } - - /** Standard implementation of a mapped iterator. **/ - class Map[B](f : A => B) extends MutableIterator[B] { - def hasNext = MutableIterator.this.hasNext - def next = f(MutableIterator.this.next) - def remove = MutableIterator.this.remove - } -} diff --git a/src/library/scala/collection/jcl/MutableSeq.scala b/src/library/scala/collection/jcl/MutableSeq.scala deleted file mode 100644 index 3971bc0984..0000000000 --- a/src/library/scala/collection/jcl/MutableSeq.scala +++ /dev/null @@ -1,123 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** A mutable sequence that supports the remove operation and is ordered. - * - * @author Sean McDirmid - */ -trait MutableSeq[A] extends Seq[A] with MutableIterable[A] { - protected class DefaultSeqIterator extends SeqIterator[Int,A] { - protected var index = 0 - override def hasNext = index < length - override def next = { - if (!hasNext) throw new NoSuchElementException("no lookahead") - index = index + 1 - MutableSeq.this.apply(index - 1) - } - override def hasPrevious = index > 0 - override def previous = { - if (!hasPrevious) throw new NoSuchElementException - index = index - 1 - MutableSeq.this.apply(index) - } - - override def nextIndex = index - override def previousIndex = { - if (index == 0) throw new NoSuchElementException - else index - 1 - } - def remove = throw new UnsupportedOperationException - } - override def elements : SeqIterator[Int,A] = new DefaultSeqIterator - - override def isEmpty = super[MutableIterable].isEmpty; - - override def apply(idx : Int) = elements.seek(idx); - override def projection : MutableSeq.Projection[A] = new MutableSeq.Projection[A] { - override def length = MutableSeq.this.length - override def elements = MutableSeq.this.elements - override def apply(idx : Int) = MutableSeq.this.apply(idx) - } - - /** Find the index of "a" in this sequence. - * @returns None if the "a" is not in this sequence. - */ - def indexOf(a : A) = elements.indexOf(a); - - override def length = { - var i = elements; - var sz = 0; - while (i.hasNext) { - sz = sz + 1; - i.next; - } - sz; - } - protected trait Filter extends MutableSeq.Projection[A] { - protected def p(a : A) : Boolean - override def elements : SeqIterator[Int,A] = new FilterIterator(MutableSeq.this.elements); - class FilterIterator(underlying : SeqIterator[Int,A]) extends SeqIterator[Int,A] { - private var index = 0; - protected def seekNext : Option[A] = { - while (underlying.hasNext) { - val next = underlying.next; - if (p(next)) return Some(next); - } - return None; - } - protected def seekPrevious : Option[A] = { - while (underlying.hasPrevious) { - val previous = underlying.previous; - if (p(previous)) return Some(previous); - } - return None; - } - def hasNext : Boolean = seekNext match { - case None => false; - case Some(_) => underlying.previous; true; - } - def nextIndex = index; - def next = seekNext match { - case None => throw new NoSuchElementException; - case Some(result) => index = index + 1; result; - } - def hasPrevious : Boolean = seekPrevious match { - case None => false; - case Some(_) => underlying.previous; true; - } - def previousIndex = { - if (index == 0) throw new NoSuchElementException; - index - 1; - } - def previous = seekPrevious match { - case None => throw new NoSuchElementException; - case Some(result) => index = index - 1; result; - } - def remove = underlying.remove; - } - } - protected class Map[B](f : A => B) extends super.Map[B](f) with MutableSeq.Projection[B] { - override def elements = MutableSeq.this.elements.map(f); - override def apply(idx : Int) = f(MutableSeq.this.apply(idx)); - override def size = length; - } -} -object MutableSeq { - trait Projection[A] extends MutableSeq[A] with MutableIterable.Projection[A] with Seq.Projection[A] { - override def projection = this - override def filter(pp : A => Boolean) : Projection[A] = new Filter { - override def p(a : A) = pp(a) - } - override def map[B](f : A => B) : Projection[B] = new Map[B](f); - } -} - diff --git a/src/library/scala/collection/jcl/Ranged.scala b/src/library/scala/collection/jcl/Ranged.scala deleted file mode 100644 index c07cc2c6c0..0000000000 --- a/src/library/scala/collection/jcl/Ranged.scala +++ /dev/null @@ -1,54 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Any collection (including maps) whose keys (or elements) are ordered. - * - * @author Sean McDirmid - */ -trait Ranged[K,A] extends scala.collection.Ranged[K,A] with MutableIterable[A] { - protected type SortedSelf <: Ranged[K,A]; - - /** Comparison function that orders keys. */ - def compare(k0: K, k1: K): Int; - - /** Creates a ranged projection of this collection. Any mutations in the - * ranged projection will update this collection and vice versa. Note: keys - * are not garuanteed to be consistent between this collection and the projection. - * This is the case for buffers where indexing is relative to the projection. - * - * @param from The lower-bound (inclusive) of the ranged projection. - * <code>None</code> if there is no lower bound. - * @param until The upper-bound (exclusive) of the ranged projection. - * <code>None</code> if there is no upper bound. - */ - def rangeImpl(from: Option[K], until: Option[K]) : SortedSelf; - /** Creates a ranged projection of this collection with no upper-bound. - ** @param from The lower-bound (inclusive) of the ranged projection. - **/ - override final def from(from: K): SortedSelf = rangeImpl(Some(from), None); - /** Creates a ranged projection of this collection with no lower-bound. - ** @param until The upper-bound (exclusive) of the ranged projection. - **/ - override final def until(until: K): SortedSelf = rangeImpl(None, Some(until)); - - /** Creates a ranged projection of this collection with both a lower-bound and an upper-bound. - ** @param from The upper-bound (exclusive) of the ranged projection. - **/ - override final def range(from: K, until: K) : SortedSelf = rangeImpl(Some(from),Some(until)); - - /** A wrapper around Java comparators. */ - protected class Comparator[K <% Ordered[K]] extends java.util.Comparator[Any] { - def compare(x0 : Any, x1 : Any) = { - x0.asInstanceOf[K].compare(x1.asInstanceOf[K]); //!!! - } - } -} diff --git a/src/library/scala/collection/jcl/SeqIterator.scala b/src/library/scala/collection/jcl/SeqIterator.scala deleted file mode 100644 index c3d65dc2a4..0000000000 --- a/src/library/scala/collection/jcl/SeqIterator.scala +++ /dev/null @@ -1,58 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** An iterator for a sequence that can move both forwards and backwards. - * over a set of ordered keys. - * - * @author Sean McDirmid - */ -trait SeqIterator[K,A] extends MutableIterator[A] { - /** @returns The index at the iterator's cursor. */ - def nextIndex: K; - - /** @returns The index of the element before the iterator's cursor. */ - def previousIndex: K; - - /** @return The previous element, will move the iterator's cursor backwards. */ - def previous: A; - - /** @return True if and only if the iterator's cursor is not at the beging of the iteration. */ - def hasPrevious : Boolean; - - /** Winds the iteration forward until index "idx" is found */ - def seek(idx: K) = { - while (nextIndex != idx) next; - next; - } - /** finds the index of the next "a" in this iteration. - * - * @param a .. - * @return <code>None</code> if "a" is not found in the iteration. - */ - def indexOf(a: A): Option[K] = { - while (hasNext) { - val ret = next; - if (ret == a) return Some(previousIndex); - } - return None; - } - - override def map[B](f: A => B) : SeqIterator[K,B] = new Map[B](f); - class Map[B](f: A => B) extends super.Map[B](f) with SeqIterator[K,B] { - override def hasPrevious = SeqIterator.this.hasPrevious; - override def previous = f(SeqIterator.this.previous); - override def previousIndex = SeqIterator.this.previousIndex; - override def nextIndex = SeqIterator.this.nextIndex; - override def map[C](g : B => C) : SeqIterator[K,C] = - SeqIterator.this.map(a => g(f(a))); - } -} diff --git a/src/library/scala/collection/jcl/Set.scala b/src/library/scala/collection/jcl/Set.scala deleted file mode 100644 index 3b39a07f1e..0000000000 --- a/src/library/scala/collection/jcl/Set.scala +++ /dev/null @@ -1,72 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** Analogous to a Java set. - * - * @author Sean McDirmid - */ -trait Set[A] extends scala.collection.mutable.Set[A] with Collection[A] { - final def contains(a : A) = has(a) - - /** Add will return false if "a" already exists in the set. **/ - override def add(a: A): Boolean - - override def ++(i: Iterable[A]) : this.type = super[Collection].++(i) - override def --(i: Iterable[A]) : this.type = super[Collection].--(i) - override def +(t: A) : this.type = super[Collection].+(t) - override def -(t: A) : this.type = super[Collection].-(t) - override final def retain(f: A => Boolean) = retainOnly(f) - override def isEmpty = super[Collection].isEmpty - override def clear() = super.clear() - override def subsetOf(set : scala.collection.Set[A]) = set match { - case set : Set[_] => set.hasAll(this) - case set => super.subsetOf(set) - } - - override def transform(f: A => A) = { - var toAdd : List[A] = Nil - val i = elements - while (i.hasNext) { - val i0 = i.next - val i1 = f(i0) - if (i0 != i1) { - i.remove; toAdd = i1 :: toAdd - } - } - addAll(toAdd) - } - class Filter(pp : A => Boolean) extends super.Filter with Set.Projection[A] { - override def p(a : A) = pp(a) - override def retainOnly(p0 : A => Boolean): Unit = - Set.this.retainOnly(e => !p(e) || p0(e)) - override def add(a : A) = { - if (!p(a)) throw new IllegalArgumentException - else Set.this.add(a) - } - } - override def projection : Set.Projection[A] = new Set.Projection[A] { - override def add(a: A): Boolean = Set.this.add(a) - override def elements = Set.this.elements - override def size = Set.this.size - override def has(a : A) : Boolean = Set.this.has(a) - } -} - -object Set { - trait Projection[A] extends Collection.Projection[A] with Set[A] { - override def filter(p : A => Boolean) : Projection[A] = new Filter(p); - override def projection = this - } - def apply[T](set : java.util.Set[T]) = new SetWrapper[T] { - val underlying = set - } -} diff --git a/src/library/scala/collection/jcl/SetWrapper.scala b/src/library/scala/collection/jcl/SetWrapper.scala deleted file mode 100644 index 74697b20aa..0000000000 --- a/src/library/scala/collection/jcl/SetWrapper.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Used to wrap Java sets. - * - * @author Sean McDirmid - */ -trait SetWrapper[A] extends Set[A] with CollectionWrapper[A] { - def underlying: java.util.Set[A]; - override def isEmpty = super[CollectionWrapper].isEmpty; - override def clear() = super[CollectionWrapper].clear; - override def size = underlying.size; -} diff --git a/src/library/scala/collection/jcl/Sorted.scala b/src/library/scala/collection/jcl/Sorted.scala deleted file mode 100644 index daaffc943c..0000000000 --- a/src/library/scala/collection/jcl/Sorted.scala +++ /dev/null @@ -1,46 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Any collection (including maps) whose keys (or elements) are ordered. - * - * @author Sean McDirmid - */ -trait Sorted[K,A] extends scala.collection.Sorted[K,A] with Ranged[K,A] { - override protected type SortedSelf <: Sorted[K,A]; - /** return as a projection the set of keys in this collection */ - override def keySet : SortedSet[K]; - - /** Creates a ranged projection of this collection. Any mutations in the - * ranged projection will update this collection and vice versa. Keys - * are garuanteed to be consistent between the collection and its projection. - * - * @param from The lower-bound (inclusive) of the ranged projection. - * <code>None</code> if there is no lower bound. - * @param until The upper-bound (exclusive) of the ranged projection. - * <code>None</code> if there is no upper bound. - */ - override def rangeImpl(from: Option[K], until: Option[K]) : SortedSelf; - - /** Create a range projection of this collection with no lower-bound. - ** @param to The upper-bound (inclusive) of the ranged projection. - **/ - final override def to(to : K): SortedSelf = { - // tough! - val i = keySet.from(to).elements; - if (!i.hasNext) return this.asInstanceOf[SortedSelf]; - val next = i.next; - if (next == to) { - if (!i.hasNext) return this.asInstanceOf[SortedSelf]; - else return until(i.next); - } else return until(next); - } -} diff --git a/src/library/scala/collection/jcl/SortedMap.scala b/src/library/scala/collection/jcl/SortedMap.scala deleted file mode 100644 index 64091b42fd..0000000000 --- a/src/library/scala/collection/jcl/SortedMap.scala +++ /dev/null @@ -1,103 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -object SortedMap { - trait Projection[K,E] extends Map.Projection[K,E] with SortedMap[K,E] { - override def projection = this - } - def apply[T,E](map0 : java.util.SortedMap[T,E]) = new SortedMapWrapper[T,E] { - val underlying = map0 - } -} -/** A map whose keys are sorted. - * - * @author Sean McDirmid - */ -trait SortedMap[K,E] extends scala.collection.SortedMap[K,E] with Map[K,E] with Sorted[K,Tuple2[K,E]] { - final protected type SortedSelf = SortedMap[K,E]; - override def compare(k0 : K, k1 : K) : Int; - override def firstKey : K = elements.next._1; - override def lastKey : K = { - val i = elements; - var last : K = i.next._1; - while (i.hasNext) last = i.next._1; - last; - } - override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] = Range(from, until); - override def keySet : SortedSet.Projection[K] = new KeySet; - - override def projection : SortedMap.Projection[K,E] = new SortedMap.Projection[K,E] { - override def elements = SortedMap.this.elements - override def size = SortedMap.this.size - override def get(k : K) = SortedMap.this.get(k) - override def put(k : K, e : E) = SortedMap.this.put(k, e) - override def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0, k1) - } - - override def lense[F](f : E => F, g : F => E) : jcl.SortedMap.Projection[K,F] = new Lense[F](f,g); - - protected class Lense[F](f : E => F, g : F => E) extends super.Lense[F](f,g) with SortedMap.Projection[K,F] { - def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0, k1); - override def filterKeys(p : K => Boolean) : SortedMap.Projection[K,F] = - SortedMap.this.projection.filterKeys(p).lense(f,g); - override def lense[G](f0 : F => G, g0 : G => F) : jcl.SortedMap.Projection[K,G] = - SortedMap.this.lense[G]({x:E => f0(f(x))}, {y:G => g(g0(y))}); - override def rangeImpl(from : Option[K], until : Option[K]) = - SortedMap.this.rangeImpl(from,until).lense(f,g); - } - protected class KeySet extends super.KeySet with SortedSet.Projection[K] { - def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1); - override def firstKey = SortedMap.this.firstKey; - override def lastKey = SortedMap.this.lastKey; - override def rangeImpl(from : Option[K], until : Option[K]) = - SortedMap.this.rangeImpl(from,until).keySet; - } - override def filterKeys(p : K => Boolean) : SortedMap.Projection[K,E] = new Filter(p); - protected class Filter(p : K => Boolean) extends super.Filter(p) with SortedMap.Projection[K,E] { - def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1); - override def filterKeys(p0 : K => Boolean) : SortedMap.Projection[K,E] = - SortedMap.this.filterKeys(k => p(k) && p0(k)); - override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap.Projection[K,E] = - SortedMap.this.Range(from, until).projection.filterKeys(p); - } - protected def Range(from : Option[K], until : Option[K]) : SortedMap.Projection[K,E] = new Range(from,until); - protected class Range(from : Option[K], until : Option[K]) extends super.Filter(key => { - ((from == None || (compare(from.get,key) <= 0)) && - (until == None || (compare(key,until.get) < 0))); - }) with SortedMap.Projection[K,E] { - def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1); - private def contains0(key : K) = - (from == None || (compare(from.get,key) <= 0)) && - (until == None || (compare(key,until.get) < 0)); - - override def contains(key : K) = SortedMap.this.contains(key) && contains0(key); - override def get(key : K) = if (!contains0(key)) None else SortedMap.this.get(key); - override def put(key : K, elem : E) = { - if (!contains0(key)) throw new IllegalArgumentException; - SortedMap.this.put(key, elem); - } - override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] = { - if (this.from != None && from == None) return rangeImpl(this.from, until); - if (this.until != None && until == None) return rangeImpl(from, this.until); - if (from != None && compare(this.from.get, from.get) > 0) return rangeImpl(this.from, until); - if (until != None && compare(this.until.get, until.get) < 0) return rangeImpl(from, this.until); - SortedMap.this.Range(from, until); - } - override def filterKeys(p : K => Boolean) : SortedMap.Projection[K,E] = new Filter(p); - protected class Filter(p : K => Boolean) extends super.Filter(p) with SortedMap.Projection[K,E] { - //def compare(k0 : K, k1 : K) = Range.this.compare(k0, k1); - override def filterKeys(p0 : K => Boolean) = Range.this.projection.filterKeys(k => p(k) && p0(k)); - override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap.Projection[K,E] = - Range.this.rangeImpl(from,until).projection.filterKeys(p); - } - } -} diff --git a/src/library/scala/collection/jcl/SortedMapWrapper.scala b/src/library/scala/collection/jcl/SortedMapWrapper.scala deleted file mode 100644 index e4edff0f82..0000000000 --- a/src/library/scala/collection/jcl/SortedMapWrapper.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** A sorted map that wraps an underlying Java sorted map. - * - * @author Sean McDirmid - */ -trait SortedMapWrapper[K,E] extends SortedMap[K,E] with MapWrapper[K,E] { - override def underlying : java.util.SortedMap[K,E]; - /** the comparator function of this sorted map is defined in terms - * of the underlying sorted map's comparator. - */ - def compare(k0 : K, k1 : K) = underlying.comparator.compare(k0,k1); - override def firstKey = underlying.firstKey.asInstanceOf[K]; - override def lastKey = underlying.lastKey.asInstanceOf[K]; - override def keySet : SortedSet.Projection[K] = new KeySet; - override protected def Range(from : Option[K], until : Option[K]) = new Range(from,until); - protected class Range(from : Option[K], until : Option[K]) extends super.Range(from,until) with SortedMapWrapper[K,E] { - val underlying = Tuple2(from,until) match { - case Tuple2(None,None) => throw new IllegalArgumentException; - case Tuple2(Some(from),None) => SortedMapWrapper.this.underlying.tailMap(from); - case Tuple2(None,Some(until)) => SortedMapWrapper.this.underlying.headMap(until); - case Tuple2(Some(from),Some(until)) => SortedMapWrapper.this.underlying.subMap(from,until); - } - override def compare(k0 : K, k1 : K) = super[SortedMapWrapper].compare(k0, k1); - } - protected class KeySet extends super[SortedMap].KeySet with SetWrapper[K] with SortedSet.Projection[K] { - val underlying = SortedMapWrapper.this.underlying.keySet; - } -} diff --git a/src/library/scala/collection/jcl/SortedSet.scala b/src/library/scala/collection/jcl/SortedSet.scala deleted file mode 100644 index f658ffae0a..0000000000 --- a/src/library/scala/collection/jcl/SortedSet.scala +++ /dev/null @@ -1,99 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; -import Predef._ - -object SortedSet { - trait Projection[A] extends Set.Projection[A] with SortedSet[A] { - override def projection = this - override def filter(p : A => Boolean) : Projection[A] = new Filter(p); - } - def apply[T](set : java.util.SortedSet[T]) = new SortedSetWrapper[T] { - val underlying = set - } - -} - -/** Analogous to a Java sorted set. - * - * @author Sean McDirmid - */ -trait SortedSet[A] extends scala.collection.SortedSet[A] with jcl.Set[A] with Sorted[A,A] { - final protected type SortedSelf = SortedSet[A]; - override def keySet = this; - def compare(a0 : A, a1 : A) : Int; - override def firstKey : A = { - val i = elements; - if (i.hasNext) i.next; - else throw new NoSuchElementException; - } - override def subsetOf(that : scala.collection.Set[A]) = super[SortedSet].subsetOf(that); - override def hasAll(that : Iterable[A]) = super[Sorted].hasAll(that.elements); - - override def lastKey : A = { - var last : A = null.asInstanceOf[A]; - val i = elements; - while (i.hasNext) last = i.next; - if (last == null) throw new NoSuchElementException; - else last; - } - override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = new Range(from, until); - override def projection : SortedSet.Projection[A] = new SortedSet.Projection[A] { - override def compare(a0 : A, a1 : A) = SortedSet.this.compare(a0, a1) - override def add(a: A): Boolean = SortedSet.this.add(a) - override def elements = SortedSet.this.elements - override def size = SortedSet.this.size - override def has(a : A) : Boolean = SortedSet.this.has(a) - } - - protected class Filter(pp : A => Boolean) extends super.Filter(pp) with SortedSet.Projection[A] { - override def p(a : A) = pp(a) - def compare(a0 : A, a1 : A) : Int = SortedSet.this.compare(a0, a1); - override def filter(p0 : A => Boolean) = SortedSet.this.projection.filter(k => p(k) && p0(k)); - } - protected class Range(from : Option[A], until : Option[A]) extends Filter(key => { - (from == None || (compare(from.get,key) <= 0)) && - (until == None || (compare(key,until.get) < 0)); - }) with SortedSet.Projection[A] { - if (from == None && until == None) throw new IllegalArgumentException; - if (from != None && until != None && !(SortedSet.this.compare(from.get, until.get) < 0)) - throw new IllegalArgumentException; - //override def elements : MutableIterator[A] = - // new RangeIterator(SortedSet.this.elements.buffered0); - private def contains1(key : A) = - (from == None || (compare(from.get,key) <= 0)) && - (until == None || (compare(key,until.get) < 0)); - override def has(elem : A) = contains1(elem) && SortedSet.this.has(elem); - override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = { - if (this.from != None && from == None) return rangeImpl(this.from, until); - if (this.until != None && until == None) return rangeImpl(from, this.until); - if (from != None && compare(this.from.get, from.get) > 0) return rangeImpl(this.from, until); - if (until != None && compare(this.until.get, until.get) < 0) return rangeImpl(from, this.until); - SortedSet.this.rangeImpl(from, until); - } - /* - class RangeIterator(underlying : MutableIterator[A]#Buffered) extends MutableIterator[A] { - if (from != None) - underlying.seekNext(a => compare(from.get, a) <= 0); - - private def okNext(a : A) = - if (until == None) true; - else compare(a, until.get) < 0; - - def hasNext = underlying.hasNext && okNext(underlying.peekNext); - def next = underlying.seekNext(okNext) match { - case Some(result) => underlying.next; result; - case None => throw new NoSuchElementException; - } - def remove = underlying.remove; - }*/ - } -} diff --git a/src/library/scala/collection/jcl/SortedSetWrapper.scala b/src/library/scala/collection/jcl/SortedSetWrapper.scala deleted file mode 100644 index c44a2274a0..0000000000 --- a/src/library/scala/collection/jcl/SortedSetWrapper.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** <p> - * A wrapper around a Java sorted set. - * </p> - * <p> - * The comparator of the sorted set matches the comparator of this set. - * </p> - * - * @author Sean McDirmid - */ -trait SortedSetWrapper[A] extends SortedSet[A] with SetWrapper[A] { - def underlying : java.util.SortedSet[A]; - /** delegates to the comparator of the underlying Java sorted set */ - override def compare(a0 : A, a1 : A) = underlying.comparator.compare(a0, a1); - override def firstKey = underlying.first.asInstanceOf[A]; - override def lastKey = underlying.last .asInstanceOf[A]; - override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = new Range(from,until); - protected class Range(from : Option[A], until : Option[A]) extends super.Range(from, until) with SortedSetWrapper[A] { - val underlying = Tuple2(from,until) match { - case Tuple2(None,Some(until)) => SortedSetWrapper.this.underlying.headSet(until); - case Tuple2(Some(from),None) => SortedSetWrapper.this.underlying.tailSet(from); - case Tuple2(Some(from),Some(until)) => SortedSetWrapper.this.underlying.subSet(from,until); - case _ => throw new IllegalArgumentException; - } - override def elements : MutableIterator[A] = super[SortedSetWrapper].elements; - } - override def toString = super.toString; -} diff --git a/src/library/scala/collection/jcl/Tests.scala b/src/library/scala/collection/jcl/Tests.scala deleted file mode 100644 index 0d69de623f..0000000000 --- a/src/library/scala/collection/jcl/Tests.scala +++ /dev/null @@ -1,79 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -import java.lang.Integer; - -private[jcl] object Tests { - - def main(args : Array[String]) : Unit = { - hashSet; - treeSet; - treeMap; - } - - def treeSet : Unit = { - val set = new TreeSet[String]; - set + "aaa" + "bbb" + "ccc" + "ddd" + "eee" + "fff"; - Console.println(set); - val rset : SortedSet[String] = set.range("b", "e"); - Console.println(rset); - rset + "bad"; - Console.println(rset); - Console.println(set); - val fset : SortedSet[String] = rset.projection.filter(_.endsWith("d")); - Console.println(fset); - fset += "cd"; - Console.println(set); - //set.projection.map(_.length).retain(x => x == 3); - Console.println(set); - Console.println(rset); - Console.println(fset); - } - - def treeMap : Unit = { - val map = new TreeMap[String,Integer]; - map + ("bb" -> 3) + ("cc" -> 4) + ("aa" -> 2) + ("dd" -> 5); - //Console.println(map); - val rmap : SortedMap[String,Integer] = map.range("b", "d"); - rmap + ("bad" -> 10); - Console.println(rmap); - //Console.println(map); - val fmap : SortedMap[String,Integer] = rmap.projection.filterKeys(k => k.length == 2); - Console.println(fmap); - } - - def hashSet = { - val set = new HashSet[String]; - set + "hello" + "world" + "you" + "to"; - Console.println(set); - val fset = set.projection.filter(s => s.length <= 3); - Console.println(fset); - fset += "xxx"; - Console.println(set); - try { - fset += "xxxx"; - throw new Error; - } catch { - case e : IllegalArgumentException => - case _ => throw new Error; - } - //val mset : MutableIterable[Int] = set // set.projection.map(s => s.length); - //Console.println(mset); - //mset.retain(n => n < 5); - Console.println(set); - val set1 = new HashSet[String] + "1" + "2" + "3"; - set ++ (set1); - Console.println(set); - set.transform(s => "x_" + s); - Console.println(set); - } -} diff --git a/src/library/scala/collection/jcl/TreeMap.scala b/src/library/scala/collection/jcl/TreeMap.scala deleted file mode 100644 index 1cbacabc8d..0000000000 --- a/src/library/scala/collection/jcl/TreeMap.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A sorted map that is backed by a Java tree map. - * - * @author Sean McDirmid - */ -class TreeMap[K <% Ordered[K], E] extends SortedMapWrapper[K, E] { tm => - val underlying = (new java.util.TreeMap[K, E](new Comparator[K])) - override def clone: TreeMap[K, E] = - new TreeMap[K, E] { - override val underlying = - tm.underlying.clone().asInstanceOf[java.util.TreeMap[K, E]] - } -} diff --git a/src/library/scala/collection/jcl/TreeSet.scala b/src/library/scala/collection/jcl/TreeSet.scala deleted file mode 100644 index 9ea94dcdfd..0000000000 --- a/src/library/scala/collection/jcl/TreeSet.scala +++ /dev/null @@ -1,26 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** Creates a sorted set that is backed by an underlying Java tree set. - * Elements of the sorted set are ordered with respect to the ordered - * view bound of <code>A</code>. - * - * @author Sean McDirmid - */ -class TreeSet[A <% Ordered[A]] extends SortedSetWrapper[A] { ts => - val underlying = new java.util.TreeSet[A](new Comparator[A]) - override def clone: TreeSet[A] = - new TreeSet[A] { - override val underlying = - ts.underlying.clone().asInstanceOf[java.util.TreeSet[A]] - } -} diff --git a/src/library/scala/collection/jcl/WeakHashMap.scala b/src/library/scala/collection/jcl/WeakHashMap.scala deleted file mode 100644 index 77ec0ab44d..0000000000 --- a/src/library/scala/collection/jcl/WeakHashMap.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** <p> - * A map that is backed by a Java weak hash map, whose keys are maintained - * as weak references. - * </p> - * <p> - * Because keys are weak references, the garbage collector can collect - * them if they are not referred to elsewhere. - * </p> - * <p> - * Useful for implementing caches. - * </p> - * - * @author Sean McDirmid - */ -class WeakHashMap[K, E](override val underlying: java.util.WeakHashMap[K, E]) extends MapWrapper[K, E] { - def this() = this(new java.util.WeakHashMap[K, E]) - override def clone: WeakHashMap[K, E] = - throw new CloneNotSupportedException("The underlying map doesn't implement the Cloneable interface") -} diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala index a9aa2db978..82864cc7ee 100644 --- a/src/library/scala/collection/mutable/ArrayBuffer.scala +++ b/src/library/scala/collection/mutable/ArrayBuffer.scala @@ -11,8 +11,7 @@ package scala.collection.mutable - -import Predef._ +import generic._ /** An implementation of the <code>Buffer</code> class using an array to * represent the assembled sequence internally. Append, update and random @@ -20,10 +19,32 @@ import Predef._ * linear in the buffer size. * * @author Matthias Zenger - * @version 1.0, 15/03/2004 + * @author Martin Odersky + * @version 2.8 */ @serializable -class ArrayBuffer[A] extends RandomAccessSeq.Mutable[A] with Buffer[A] with ResizableArray[A] { +class ArrayBuffer[A](override protected val initialSize: Int) + extends Buffer[A] + with BufferTemplate[A, ArrayBuffer[A]] + with VectorTemplate[A, ArrayBuffer[A]] + with Builder[A, ArrayBuffer[A], Any] + with ResizableArray[A] { + + import collection.Traversible + + def this() = this(16) + + def clear() { reduceToSize(0) } + + override def sizeHint(len: Int) { + val newarray = new Array[AnyRef](len min 1) + Array.copy(array, 0, newarray, 0, size0) + array = newarray + } + + override protected[this] def newBuilder = ArrayBuffer.newBuilder + override def traversibleBuilder[B]: Builder[B, ArrayBuffer[B], Any] = ArrayBuffer.newBuilder[B] + /** Appends a single element to this buffer and returns * the identity of the buffer. It takes constant time. * @@ -39,28 +60,17 @@ class ArrayBuffer[A] extends RandomAccessSeq.Mutable[A] with Buffer[A] with Resi * via its <code>elements</code> method. The identity of the * buffer is returned. * - * @param iter the iterable object. + * @param iter the iterfable object. * @return the updated buffer. */ - override def ++=(iter: Iterable[A]) { iter copyToBuffer this } - - override def ++[B >: A](that: Iterable[B]) : ArrayBuffer[B] = { - val buf = new ArrayBuffer[B] - this copyToBuffer buf - that copyToBuffer buf - buf - } - - /** Appends a number of elements in an array - * - * @param src the array - * @param start the first element to append - * @param len the number of elements to append - */ - override def ++=(src: Array[A], start: Int, len: Int) { - ensureSize(size0 + len) - Array.copy(src, start, array, size0, len) - size0 += len + override def ++=(iter: Traversible[A]) = iter match { + case v: Vector[_] => + val n = v.length + ensureSize(size0 + n) + v.copyToArray(array.asInstanceOf[scala.Array[Any]], size0, n) + size0 += n + case _ => + super.++=(iter) } /** Prepends a single element to this buffer and return @@ -70,7 +80,7 @@ class ArrayBuffer[A] extends RandomAccessSeq.Mutable[A] with Buffer[A] with Resi * @param elem the element to append. * @return the updated buffer. */ - def +:(elem: A): Buffer[A] = { + def +:(elem: A): this.type = { ensureSize(size0 + 1) copy(0, 1, size0) array(0) = elem.asInstanceOf[AnyRef] @@ -78,19 +88,6 @@ class ArrayBuffer[A] extends RandomAccessSeq.Mutable[A] with Buffer[A] with Resi this } - /** Returns the i-th element of this ArrayBuffer. It takes constant time. - * - * @param i the specified index. - * @return the i-th element. - * @throws Predef.IndexOutOfBoundException if <code>i</code> is out of bounds. - */ - override def apply(i: Int) = { - if ((i < 0) || (i >= size0)) - throw new IndexOutOfBoundsException(i.toString()) - else - array(i).asInstanceOf[A] - } - /** Prepends a number of elements provided by an iterable object * via its <code>elements</code> method. The identity of the * buffer is returned. @@ -98,7 +95,7 @@ class ArrayBuffer[A] extends RandomAccessSeq.Mutable[A] with Buffer[A] with Resi * @param iter the iterable object. * @return the updated buffer. */ - override def ++:(iter: Iterable[A]): Buffer[A] = { insertAll(0, iter); this } + override def ++:(iter: Traversible[A]): this.type = { insertAll(0, iter); this } /** Inserts new elements at the index <code>n</code>. Opposed to method * <code>update</code>, this method will not replace an element with a @@ -108,81 +105,60 @@ class ArrayBuffer[A] extends RandomAccessSeq.Mutable[A] with Buffer[A] with Resi * @param iter the iterable object providing all elements to insert. * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds. */ - def insertAll(n: Int, iter: Iterable[A]) { + def insertAll(n: Int, seq: Traversible[A]) { if ((n < 0) || (n > size0)) - throw new IndexOutOfBoundsException("cannot insert element at " + n); - val xs = iter.elements.toList + throw new IndexOutOfBoundsException(n.toString) + val xs = seq.toList val len = xs.length ensureSize(size0 + len) copy(n, n + len, size0 - n) - xs.copyToArray(array.asInstanceOf[Array[Any]], n) + xs.copyToArray(array.asInstanceOf[scala.Array[Any]], n) size0 += len } - /** Replace element at index <code>n</code> with the new element - * <code>newelem</code>. It takes constant time. - * - * @param n the index of the element to replace. - * @param newelem the new element. - * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds. - */ - def update(n: Int, newelem: A) { - if ((n < 0) || (n >= size0)) - throw new IndexOutOfBoundsException("cannot update element at " + n) - else { - val res = array(n).asInstanceOf[A] - array(n) = newelem.asInstanceOf[AnyRef] - res - } - } - /** Removes the element on a given index position. It takes time linear in * the buffer size. * - * @param n the index which refers to the element to delete. + * @param n the index which refers to the first element to delete. + * @param count the number of elemenets to delete * @return the updated array buffer. * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds. */ - def remove(n: Int): A = { + override def remove(n: Int, count: Int) { if ((n < 0) || (n >= size0)) - throw new IndexOutOfBoundsException("cannot remove element at " + n); - val res = array(n).asInstanceOf[A] - copy(n + 1, n, size0 - n - 1) - size0 -= 1 - res + throw new IndexOutOfBoundsException(n.toString) + copy(n + count, n, size0 - (n + count)) + size0 -= count } - /** Clears the buffer contents. + /** Removes the element on a given index position + * + * @param n the index which refers to the element to delete. + * @return The element that was formerly at position `n` */ - def clear() { - size0 = 0 + def remove(n: Int): A = { + val result = apply(n) + remove(n, 1) + result } /** Return a clone of this buffer. * * @return an <code>ArrayBuffer</code> with the same elements. */ - override def clone(): Buffer[A] = { - val res = new ArrayBuffer[A] - res ++= this - res - } + override def clone(): ArrayBuffer[A] = new ArrayBuffer[A] ++ this - /** Checks if two buffers are structurally identical. - * - * @return true, iff both buffers contain the same sequence of elements. - */ - override def equals(obj: Any): Boolean = obj match { - case that: ArrayBuffer[_] => - this.length == that.length && - elements.zip(that.elements).forall { - case (thiselem, thatelem) => thiselem == thatelem - } - case _ => - false - } + def result: ArrayBuffer[A] = this /** Defines the prefix of the string representation. */ - override protected def stringPrefix: String = "ArrayBuffer" + override def stringPrefix: String = "ArrayBuffer" } + +/* Factory object for `ArrayBuffer` class */ +object ArrayBuffer extends SequenceFactory[ArrayBuffer] { + type Coll = ArrayBuffer[_] + implicit def builderFactory[A]: BuilderFactory[A, ArrayBuffer[A], Coll] = new BuilderFactory[A, ArrayBuffer[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, ArrayBuffer[A], Any] = new ArrayBuffer[A] +} + diff --git a/src/library/scala/collection/mutable/ArrayStack.scala b/src/library/scala/collection/mutable/ArrayStack.scala index f4abec337b..984f8a4c0a 100644 --- a/src/library/scala/collection/mutable/ArrayStack.scala +++ b/src/library/scala/collection/mutable/ArrayStack.scala @@ -8,7 +8,7 @@ // $Id$ - +// !!! todo: integrate in collections framework package scala.collection.mutable; private object Utils{ @@ -32,7 +32,7 @@ private object Utils{ * @author David MacIver */ class ArrayStack[T] private(private var table : Array[AnyRef], - private var index : Int) extends Collection[T]{ + private var index : Int) extends Iterable[T]{ def this() = this(new Array[AnyRef](1), 0); /** @@ -59,13 +59,19 @@ class ArrayStack[T] private(private var table : Array[AnyRef], /** * View the top element of the stack. + * @deprecated use top instead + */ + def peek = top + + /** + * View the top element of the stack. */ - def peek = table(index - 1).asInstanceOf[T] + def top = table(index - 1).asInstanceOf[T] /** * Duplicate the top element of the stack. */ - def dup = push(peek); + def dup = push(top); /** * Empties the stack. @@ -121,7 +127,7 @@ class ArrayStack[T] private(private var table : Array[AnyRef], */ def reduceWith(f : (T, T) => T) = while(size > 1) combine(f) - def size = index; + override def size = index; /** * Evaluates the expression, preserving the contents of the stack so that diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala index bfc02a5767..5ec33a059c 100644 --- a/src/library/scala/collection/mutable/BitSet.scala +++ b/src/library/scala/collection/mutable/BitSet.scala @@ -1,100 +1,50 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - package scala.collection.mutable +import generic._ -/** - * The class <code>BitSet</code> implements mutable, resizable Bit sets - * - * @author Burak Emir, Nikolay Mihaylov - * @version 1.1 - * - * @param initSize: initial size in bits - */ +/** A class for mutable bitsets */ +class BitSet(initSize: Int) extends Set[Int] with collection.BitSet with BitSetTemplate[BitSet] { -@serializable -class BitSet(initSize: Int) extends collection.BitSet with Set[Int] { + override def empty = BitSet.empty - import compat.Platform.{arraycopy, arrayclear} - - /** default constructor, initial size of 512 bits. */ def this() = this(0) - /** Ensures that this bitset can store at least <code>n</code> bits. - * - * @param n ... - */ - def ensureCapacity(n: Int): Unit = - if (capacity < n) { - if (nbits(arr.length) < n) { - val newn = memsize(n) - var newsize = if (arr.length == 0) newn else arr.length * 2 - while (newn > newsize) - newsize = newsize * 2; - val newarr = new Array[Int](newsize) - arraycopy(arr, 0, newarr, 0, arr.length) - arr = newarr - } - capacity = n - } - - /** - * Sets <code>i-th</code> bit to true. - * No restriction on <code>i</code> - */ - def +=(i: Int): Unit = { - ensureCapacity(i+1) - val oldInt = arr(offset(i)) - val newInt = oldInt | mask(i) - if (oldInt != newInt) { - arr(offset(i)) = newInt - size = size + 1 + protected var elems: Array[Long] = new Array[Long]((initSize + 63) >> 6 max 1) + + protected def nwords = elems.length + protected def word(idx: Int): Long = + if (idx < nwords) elems(idx) else 0L + protected def updateWord(idx: Int, w: Long): BitSet = { + if (idx >= nwords) { + var newlen = nwords + while (idx >= newlen) newlen = newlen * 2 + val elems1 = new Array[Long](newlen) + Array.copy(elems, 0, elems1, 0, nwords) + elems = elems1 } + elems(idx) = w + this } - /** Clears the <code>i</code>-th bit. - * - * @param i the <code>i</code>-th element of the bit set. - */ - def -=(i: Int): Unit = { - if (i >= capacity) return; - val oldInt = arr(offset(i)) - val newInt = oldInt & ~mask(i) - if (oldInt != newInt) { - arr(offset(i)) = newInt - size = size - 1 - } - } - - /** Clears all bits of the set. - */ - override def clear(): Unit = { - arrayclear(arr) - size = 0 + protected def fromArray(words: Array[Long]): BitSet = { + val s = new BitSet; s.elems = words; s } - def toImmutable: collection.immutable.BitSet = - new immutable.BitSet(size, capacity, arr, true) + override def += (elem: Int) { super.+(elem) } - override def clone(): BitSet = new BitSet(capacity) { - arraycopy(BitSet.this.arr, 0, arr, 0, arr.length) - size = BitSet.this.size - capacity = BitSet.this.capacity - } + override def -= (elem: Int) { super.-(elem) } - var size: Int = 0 + override def + (elem: Int): this.type = { +=(elem); this } - var capacity: Int = initSize + override def - (elem: Int): this.type = { -=(elem); this } - protected var arr: Array[Int] = new Array[Int](memsize(initSize)) + def toImmutable = immutable.BitSet.fromArray(elems) +} +/** A factory object for mutable bitsets */ +object BitSet { + def empty: BitSet = new BitSet + def apply(bits: Int*): BitSet = { + var s = empty; for (b <- bits) s += b; s + } } diff --git a/src/library/scala/collection/mutable/Buffer.scala b/src/library/scala/collection/mutable/Buffer.scala index 9e56d841d0..5fed53ae04 100644 --- a/src/library/scala/collection/mutable/Buffer.scala +++ b/src/library/scala/collection/mutable/Buffer.scala @@ -11,276 +11,27 @@ package scala.collection.mutable - -import Predef._ +import generic._ /** Buffers are used to create sequences of elements incrementally by * appending, prepending, or inserting new elements. It is also * possible to access and modify elements in a random access fashion * via the index of the element in the current sequence. - * - * @author Matthias Zenger - * @version 1.1, 02/03/2004 - */ + * + * @author Matthias Zenger + * @author Martin Odersky + * @version 2.8 + */ @cloneable -trait Buffer[A] extends AnyRef - with Seq[A] - with Scriptable[Message[(Location, A)]] - with CloneableCollection -{ - - /** Append a single element to this buffer. - * - * @param elem the element to append. - */ - def +=(elem: A): Unit - - /** Append a two or more elements to this buffer. - * - * enable this for 2.8.0! - * - * @param elem1 the first element to append. - * @param elem2 the second element to append. - * @param elems the remaining elements to append. - def +=(elem1: A, elem2: A, elems: A*): Unit = { - this += elem1 - this += elem2 - this ++= elems - } - */ - - /** Append a single element to this buffer and return - * the identity of the buffer. - * - * @param elem the element to append. - */ - def +(elem: A): Buffer[A] = { this += elem; this } - - /** Append two or more elements to this buffer and return - * the identity of the buffer. - * - * enable this for 2.8.0! - * - * @param elem1 the first element to append. - * @param elem2 the second element to append. - * @param elems the remaining elements to append. - def +(elem1: A, elem2: A, elems: A*): Buffer[A] = - this + elem1 + elem2 ++ elems - */ - - /** Prepend a single element to this buffer and return - * the identity of the buffer. - * - * @param elem the element to append. - */ - def +:(elem: A): Buffer[A] - - /** Appends a number of elements provided by an iterator - * - * @param iter the iterator. - */ - def ++=(iter: Iterator[A]) { iter foreach += } - - /** Appends a number of elements provided by an iterable object - * via its <code>elements</code> method. - * - * @param iter the iterable object. - */ - def ++=(iter: Iterable[A]) { ++=(iter.elements) } - - /** Appends a number of elements in an array - * - * @param src the array - * @param start the first element to append - * @param len the number of elements to append - */ - def ++=(src: Array[A], start: Int, len: Int) { - var i = start - val end = i + len - while (i < end) { - this += src(i) - i += 1 - } - } - /** return a read only alias of this buffer - */ - def readOnly : Seq[A] - - /** Appends a number of elements provided by an iterable object - * via its <code>elements</code> method. The identity of the - * buffer is returned. - * - * @param iter the iterable object. - * @return the updated buffer. - */ - def ++(iter: Iterable[A]): Buffer[A] = { this ++= iter; this } - - override def ++[B >: A](that : Iterable[B]) : Seq[B] = { - val buf = new ArrayBuffer[B] - this copyToBuffer buf - that copyToBuffer buf - buf - } - - /** Appends a number of elements provided by an iterator - * via its <code>elements</code> method. The identity of the - * buffer is returned. - * - * @param iter the iterator - * @return the updated buffer. - */ - def ++(iter: Iterator[A]): Buffer[A] = { this ++= iter; this } - - /** Prepends a number of elements provided by an iterable object - * via its <code>elements</code> method. The identity of the - * buffer is returned. - * - * @param iter the iterable object. - */ - def ++:(iter: Iterable[A]): Buffer[A] = { - iter.elements.toList.reverse.foreach(e => e +: this) - this - } - - /** Removes a single element from this buffer, at its first occurrence. - * If the list does not contain that element, it is unchanged - * - * @param x the element to remove. - */ - def -= (x: A) { - val i = indexOf(x) - if(i != -1) remove(i) - } - - /** Appends a sequence of elements to this buffer. - * - * @param elems the elements to append. - */ - def append(elems: A*) { this ++= elems } - - /** Appends a number of elements provided by an iterable object - * via its <code>elements</code> method. - * - * @param iter the iterable object. - */ - def appendAll(iter: Iterable[A]) { this ++= iter } - - /** Prepend an element to this list. - * - * @param elem the element to prepend. - */ - def prepend(elems: A*) { elems ++: this } - - /** Prepends a number of elements provided by an iterable object - * via its <code>elements</code> method. The identity of the - * buffer is returned. - * - * @param iter the iterable object. - */ - def prependAll(iter: Iterable[A]) { iter ++: this } - - /** Inserts new elements at the index <code>n</code>. Opposed to method - * <code>update</code>, this method will not replace an element with a - * one. Instead, it will insert the new elements at index <code>n</code>. - * - * @param n the index where a new element will be inserted. - * @param elems the new elements to insert. - */ - def insert(n: Int, elems: A*) { insertAll(n, elems) } - - /** Inserts new elements at the index <code>n</code>. Opposed to method - * <code>update</code>, this method will not replace an element with a - * one. Instead, it will insert a new element at index <code>n</code>. - * - * @param n the index where a new element will be inserted. - * @param iter the iterable object providing all elements to insert. - */ - def insertAll(n: Int, iter: Iterable[A]): Unit - - /** Replace element at index <code>n</code> with the new element - * <code>newelem</code>. - * - * @param n the index of the element to replace. - * @param newelem the new element. - */ - def update(n: Int, newelem: A): Unit - - /** Removes the element on a given index position. - * - * @param n the index which refers to the element to delete. - */ - def remove(n: Int): A - - /** Removes the first <code>n</code> elements. - * - * @param n the number of elements to remove from the beginning - * of this buffer. - */ - def trimStart(n: Int) { - var i = n - while (i > 0) { remove(0); i -= 1 } - } - - /** Removes the last <code>n</code> elements. - * - * @param n the number of elements to remove from the end - * of this buffer. - */ - def trimEnd(n: Int) { - var i = n - while (i > 0) { remove(length - 1); i -= 1 } - } - - /** Clears the buffer contents. - */ - def clear(): Unit - - /** Send a message to this scriptable object. - * - * @param cmd the message to send. - */ - def <<(cmd: Message[(Location, A)]) { - cmd match { - case Include((l, elem)) => l match { - case Start => prepend(elem) - case End => append(elem) - case Index(n) => insert(n, elem) - case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") - } - case Update((l, elem)) => l match { - case Start => update(0, elem) - case End => update(length - 1, elem) - case Index(n) => update(n, elem) - case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") - } - case Remove((l, _)) => l match { - case Start => remove(0) - case End => remove(length - 1) - case Index(n) => remove(n) - case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") - } - case Reset() => clear - case s: Script[_] => s.elements foreach << - case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") - } - } - - /** Return a clone of this buffer. - * - * @return a buffer with the same elements. - */ - override def clone(): Buffer[A] = super.clone().asInstanceOf[Buffer[A]] - - /** The hashCode method always yields an error, since it is not - * safe to use buffers as keys in hash tables. - * - * @return never. - */ - override def hashCode(): Int = - throw new UnsupportedOperationException("unsuitable as hash key") - - /** Defines the prefix of the string representation. - */ - override protected def stringPrefix: String = "Buffer" +trait Buffer[A] extends Sequence[A] with BufferTemplate[A, Buffer[A]] { + override protected[this] def newBuilder = Buffer.newBuilder + override def traversibleBuilder[B]: Builder[B, Buffer[B], Any] = Buffer.newBuilder[B] +} +/* Factory object for `Buffer` trait */ +object Buffer extends SequenceFactory[Buffer] { + type Coll = Buffer[_] + implicit def builderFactory[A]: BuilderFactory[A, Buffer[A], Coll] = new BuilderFactory[A, Buffer[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Buffer[A], Any] = new ArrayBuffer } + diff --git a/src/library/scala/collection/mutable/BufferProxy.scala b/src/library/scala/collection/mutable/BufferProxy.scala index 92d26ab2b9..e6406e2bb2 100644 --- a/src/library/scala/collection/mutable/BufferProxy.scala +++ b/src/library/scala/collection/mutable/BufferProxy.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -154,3 +155,4 @@ trait BufferProxy[A] extends Buffer[A] with Proxy { def self = BufferProxy.this.self.clone() } } +*/ diff --git a/src/library/scala/collection/mutable/CloneableCollection.scala b/src/library/scala/collection/mutable/CloneableCollection.scala index c49fcf308c..8dea90eb2a 100644 --- a/src/library/scala/collection/mutable/CloneableCollection.scala +++ b/src/library/scala/collection/mutable/CloneableCollection.scala @@ -13,7 +13,8 @@ package scala.collection.mutable /** The J2ME version of the library defined this trait with a clone method * to substitute for the lack of Object.clone there + * @deprecated use Cloneable instead */ -trait CloneableCollection { +@deprecated trait CloneableCollection { override def clone(): AnyRef = super.clone() } diff --git a/src/library/scala/collection/mutable/DefaultEntry.scala b/src/library/scala/collection/mutable/DefaultEntry.scala index 5d0c64fc27..16a4448650 100644 --- a/src/library/scala/collection/mutable/DefaultEntry.scala +++ b/src/library/scala/collection/mutable/DefaultEntry.scala @@ -11,8 +11,6 @@ package scala.collection.mutable -import Predef._ - @serializable final class DefaultEntry[A, B](val key: A, var value: B) extends HashEntry[A, DefaultEntry[A, B]] diff --git a/src/library/scala/collection/mutable/DefaultMapModel.scala b/src/library/scala/collection/mutable/DefaultMapModel.scala index 803849b70b..de515ded7d 100644 --- a/src/library/scala/collection/mutable/DefaultMapModel.scala +++ b/src/library/scala/collection/mutable/DefaultMapModel.scala @@ -11,8 +11,6 @@ package scala.collection.mutable -import Predef._ - /** This class is used internally. It implements the mutable <code>Map</code> * class in terms of three functions: <code>findEntry</code>, * <code>addEntry</code>, and <code>entries</code>. diff --git a/src/library/scala/collection/mutable/DoubleLinkedList.scala b/src/library/scala/collection/mutable/DoubleLinkedList.scala index db2a6299b4..6b8174357a 100644 --- a/src/library/scala/collection/mutable/DoubleLinkedList.scala +++ b/src/library/scala/collection/mutable/DoubleLinkedList.scala @@ -1,7 +1,7 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ @@ -11,42 +11,26 @@ package scala.collection.mutable +import generic._ -/** This extensible class may be used as a basis for implementing double - * linked lists. Type variable <code>A</code> refers to the element type - * of the list, type variable <code>This</code> is used to model self - * types of linked lists. +/** This class implements single linked lists where both the head (<code>elem</code>) + * and the tail (<code>next</code>) are mutable. * - * @author Matthias Zenger - * @version 1.0, 08/07/2003 + * @author Matthias Zenger + * @author Martin Odersky + * @version 2.8 */ -abstract class DoubleLinkedList[A, This >: Null <: DoubleLinkedList[A, This]] - extends SingleLinkedList[A, This] -{ self: This => - - var prev: This - - override def append(that: This): Unit = - if (that eq null) - () - else if (next eq null) { - next = that - that.prev = this - } else - next.append(that) - - override def insert(that: This): Unit = if (that ne null) { - that.append(next) - next = that - that.prev = this - } - - def remove() { - if (next ne null) - next.prev = prev - if (prev ne null) - prev.next = next - prev = null - next = null - } +@serializable +class DoubleLinkedList[A]/*(_elem: A, _next: DoubleLinkedList[A])*/ extends LinearSequence[A] with DoubleLinkedListTemplate[A, DoubleLinkedList[A]] { + override protected[this] def newBuilder = DoubleLinkedList.newBuilder + override def traversibleBuilder[B]: Builder[B, DoubleLinkedList[B], Any] = DoubleLinkedList.newBuilder[B] } + +object DoubleLinkedList extends SequenceFactory[DoubleLinkedList] { + type Coll = DoubleLinkedList[_] + implicit def builderFactory[A]: BuilderFactory[A, DoubleLinkedList[A], Coll] = new BuilderFactory[A, DoubleLinkedList[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, DoubleLinkedList[A], Any] = null // !!! +} + + + diff --git a/src/library/scala/collection/mutable/FlatHashTable.scala b/src/library/scala/collection/mutable/FlatHashTable.scala index fa31d81d2c..c4ea42a3dd 100644 --- a/src/library/scala/collection/mutable/FlatHashTable.scala +++ b/src/library/scala/collection/mutable/FlatHashTable.scala @@ -113,7 +113,7 @@ trait FlatHashTable[A] { def elements = new Iterator[A] { private var i = 0 def hasNext: Boolean = { - while (i < table.length && (null == table(i))) i += 1; + while (i < table.length && (null == table(i))) i += 1 i < table.length } def next(): A = diff --git a/src/library/scala/collection/jcl/HashSet.scala b/src/library/scala/collection/mutable/HashEntry.scala index fb910fdd45..01cd59f8d8 100644..100755 --- a/src/library/scala/collection/jcl/HashSet.scala +++ b/src/library/scala/collection/mutable/HashEntry.scala @@ -1,21 +1,13 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ +package scala.collection.mutable -// $Id$ - -package scala.collection.jcl - -/** A hash set that is backed by a Java hash set. - * - * @author Sean McDirmid - */ -class HashSet[A](override val underlying: java.util.HashSet[A]) extends SetWrapper[A] { - def this() = this(new java.util.HashSet[A]) - override def clone: HashSet[A] = - new HashSet[A](underlying.clone().asInstanceOf[java.util.HashSet[A]]) +trait HashEntry [A, E] { + val key: A + var next: E = _ } diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index 2b3ce51cc1..654c6f7529 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -11,30 +11,30 @@ package scala.collection.mutable -import Predef._ +import generic._ -/** This class implements mutable maps using a hashtable. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.0, 31/12/2006 - */ -object HashMap { - - /** The empty map of this type */ - def empty[A, B] = new HashMap[A, B] - - /** The canonical factory for this type - */ - def apply[A, B](elems: (A, B)*) = empty[A, B] ++ elems -} @serializable -class HashMap[A, B] extends Map[A,B] with HashTable[A] with DefaultMapModel[A,B] { +class HashMap[A, B] extends Map[A, B] with MutableMapTemplate[A, B, HashMap[A, B]] with HashTable[A] with DefaultMapModel[A, B] { + + override def empty: HashMap[A, B] = HashMap.empty[A, B] + override def mapBuilder[A, B]: Builder[(A, B), HashMap[A, B], Any] = HashMap.newBuilder[A, B] def -= (key: A) { removeEntry(key) } override def clear() = super.clear() - override def clone(): Map[A, B] = new HashMap[A, B] ++ this + override def size: Int = super[HashTable].size +} + +/** This class implements mutable maps using a hashtable. + * + * @author Matthias Zenger + * @author Martin Odersky + * @version 2.8 + */ +object HashMap extends MutableMapFactory[HashMap] { + type Coll = HashMap[_, _] + implicit def builderFactory[A, B]: BuilderFactory[(A, B), HashMap[A, B], Coll] = new BuilderFactory[(A, B), HashMap[A, B], Coll] { def apply(from: Coll) = from.mapBuilder[A, B] } + def empty[A, B]: HashMap[A, B] = new HashMap[A, B] } diff --git a/src/library/scala/collection/mutable/HashSet.scala b/src/library/scala/collection/mutable/HashSet.scala index 019d79ed09..14f2d00013 100644 --- a/src/library/scala/collection/mutable/HashSet.scala +++ b/src/library/scala/collection/mutable/HashSet.scala @@ -11,24 +11,21 @@ package scala.collection.mutable +import generic._ + /** This class implements mutable sets using a hashtable. * * @author Matthias Zenger * @author Martin Odersky * @version 2.0, 31/12/2006 */ -object HashSet { +@serializable +class HashSet[A] extends Set[A] with SetTemplate[A, HashSet[A]] with FlatHashTable[A] { - /** The empty map of this type */ - def empty[A] = new HashSet[A] + override def empty = HashSet.empty + override def traversibleBuilder[B]: Builder[B, HashSet[B], Any] = HashSet.newBuilder[B] - /** The canonical factory for this type - */ - def apply[A](elems: A*) = empty[A] ++ elems -} - -@serializable -class HashSet[A] extends Set[A] with FlatHashTable[A] { + override def size = super.size def contains(elem: A): Boolean = containsEntry(elem) @@ -38,6 +35,23 @@ class HashSet[A] extends Set[A] with FlatHashTable[A] { override def clear() = super.clear() - override def clone(): Set[A] = new HashSet[A] ++ this + override def foreach(f: A => Unit) { + var i = 0 + val len = table.length + while (i < len) { + val elem = table(i) + if (elem ne null) f(elem.asInstanceOf[A]) + i += 1 + } + } + + override def clone(): HashSet[A] = new HashSet[A] ++ this +} + +/** Factory object for `HashSet` class */ +object HashSet extends SetFactory[HashSet] { + type Coll = HashSet[_] + implicit def builderFactory[A]: BuilderFactory[A, HashSet[A], Coll] = new BuilderFactory[A, HashSet[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def empty[A]: HashSet[A] = new HashSet[A] } diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala index a66d30cf44..1cd4698b01 100644 --- a/src/library/scala/collection/mutable/HashTable.scala +++ b/src/library/scala/collection/mutable/HashTable.scala @@ -163,10 +163,4 @@ trait HashTable[A] extends AnyRef { protected final def index(hcode: Int) = improve(hcode) & (table.length - 1) } -trait HashEntry[A, E] { - val key: A - var next: E = _ -} - - diff --git a/src/library/scala/collection/mutable/History.scala b/src/library/scala/collection/mutable/History.scala index fe5d1beca2..e90f570c53 100644 --- a/src/library/scala/collection/mutable/History.scala +++ b/src/library/scala/collection/mutable/History.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -46,3 +47,4 @@ class History[A, B] extends AnyRef with Subscriber[A, B] with Collection[(B, A)] def clear(): Unit = log.clear } +*/ diff --git a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala index b62904da2d..0aa3dddcaa 100644 --- a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala +++ b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala @@ -1,4 +1,5 @@ -/* __ *\ +/* TODO: Reintegrate +* /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** @@ -63,3 +64,4 @@ extends Map[A, B] override def toString() = imap.toString() } +*/ diff --git a/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala b/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala index fc1f63903f..894802cecf 100644 --- a/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala +++ b/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -47,3 +48,4 @@ class ImmutableSetAdaptor[A](protected var set: immutable.Set[A]) extends Set[A] override def clear(): Unit = { set = set.empty } } +*/ diff --git a/src/library/scala/collection/mutable/Iterable.scala b/src/library/scala/collection/mutable/Iterable.scala new file mode 100755 index 0000000000..52a42c5e09 --- /dev/null +++ b/src/library/scala/collection/mutable/Iterable.scala @@ -0,0 +1,29 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.collection.mutable + +import generic._ + +/** A subtrait of collection.Iterable which represents iterables + * that can be mutated. + * + * @autor Martin Odersky + * @version 2.8 + */ +trait Iterable[A] extends Traversible[A] with collection.Iterable[A] with IterableTemplate[A, Iterable[A]] { self => + override protected[this] def newBuilder = Iterable.newBuilder + override def traversibleBuilder[B]: Builder[B, Iterable[B], Any] = Iterable.newBuilder[B] +} + +/* A factory object for the trait `Iterable` */ +object Iterable extends TraversibleFactory[Iterable] { + type Coll = Iterable[_] + implicit def builderFactory[A]: BuilderFactory[A, Iterable[A], Coll] = new BuilderFactory[A, Iterable[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Iterable[A], Any] = new ArrayBuffer +} + diff --git a/src/library/scala/collection/mutable/JavaMapAdaptor.scala b/src/library/scala/collection/mutable/JavaMapAdaptor.scala index dbf49c0f41..cb5d8b8931 100644 --- a/src/library/scala/collection/mutable/JavaMapAdaptor.scala +++ b/src/library/scala/collection/mutable/JavaMapAdaptor.scala @@ -21,7 +21,7 @@ package scala.collection.mutable */ @deprecated class JavaMapAdaptor[A, B](jmap: java.util.Map[A, B]) extends Map[A, B] { - def size: Int = jmap.size() + override def size: Int = jmap.size() def get(key: A): Option[B] = if (jmap.containsKey(key)) Some(jmap.get(key).asInstanceOf[B]) else None @@ -55,7 +55,7 @@ package scala.collection.mutable } } - def update(key: A, value: B): Unit = { val x = jmap.put(key, value); } + def update(key: A, value: B) { jmap.put(key, value) } def -= (key: A): Unit = { val x = jmap.remove(key); } diff --git a/src/library/scala/collection/mutable/JavaSetAdaptor.scala b/src/library/scala/collection/mutable/JavaSetAdaptor.scala index 8cc1e024ee..ae82f3fd0f 100644 --- a/src/library/scala/collection/mutable/JavaSetAdaptor.scala +++ b/src/library/scala/collection/mutable/JavaSetAdaptor.scala @@ -21,7 +21,7 @@ package scala.collection.mutable */ @deprecated class JavaSetAdaptor[A](jset: java.util.Set[A]) extends Set[A] { - def size: Int = jset.size() + override def size: Int = jset.size() override def isEmpty: Boolean = jset.isEmpty() @@ -45,3 +45,4 @@ package scala.collection.mutable res } } + diff --git a/src/library/scala/collection/mutable/LinearSequence.scala b/src/library/scala/collection/mutable/LinearSequence.scala new file mode 100755 index 0000000000..d31da40386 --- /dev/null +++ b/src/library/scala/collection/mutable/LinearSequence.scala @@ -0,0 +1,17 @@ +package scala.collection.mutable + +import generic._ + +/** A subtrait of collection.Sequence which represents sequences + * that cannot be mutated. + */ +trait LinearSequence[A] extends Sequence[A] with collection.LinearSequence[A] with LinearSequenceTemplate[A, LinearSequence[A]] { + override protected[this] def newBuilder = LinearSequence.newBuilder + override def traversibleBuilder[B]: Builder[B, LinearSequence[B], Any] = LinearSequence.newBuilder[B] +} + +object LinearSequence extends SequenceFactory[LinearSequence] { + type Coll = LinearSequence[_] + implicit def builderFactory[A]: BuilderFactory[A, LinearSequence[A], Coll] = new BuilderFactory[A, LinearSequence[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, LinearSequence[A], Any] = new MutableList[A] +} diff --git a/src/library/scala/collection/mutable/LinkedHashMap.scala b/src/library/scala/collection/mutable/LinkedHashMap.scala index 302c3de9b4..bee3da8472 100644 --- a/src/library/scala/collection/mutable/LinkedHashMap.scala +++ b/src/library/scala/collection/mutable/LinkedHashMap.scala @@ -31,6 +31,10 @@ object LinkedHashMap { @serializable class LinkedHashMap[A, B] extends Map[A,B] with HashTable[A] with DefaultMapModel[A,B] { + + override def empty = LinkedHashMap.empty + override def size = super[HashTable].size + private var ordered = List[Entry]() def remove(key: A): Option[B] = removeEntry(key) match { diff --git a/src/library/scala/collection/mutable/LinkedHashSet.scala b/src/library/scala/collection/mutable/LinkedHashSet.scala index d4962f34cb..620cd31c15 100644 --- a/src/library/scala/collection/mutable/LinkedHashSet.scala +++ b/src/library/scala/collection/mutable/LinkedHashSet.scala @@ -10,18 +10,25 @@ package scala.collection.mutable +import generic._ +//!!! todo make inherit from HashSet. object LinkedHashSet { /** The empty map of this type */ def empty[A] = new LinkedHashSet[A] /** The canonical factory for this type */ - def apply[A](elems: A*) = empty[A] ++ elems + def apply[A](elems: A*) = empty[A] ++ collection.Iterable.fromOld(elems) } @serializable -class LinkedHashSet[A] extends Set[A] with FlatHashTable[A] { +class LinkedHashSet[A] extends Set[A] with SetTemplate[A, LinkedHashSet[A]] with FlatHashTable[A] { + + override def empty = LinkedHashSet.empty + + override def size = super.size + private var ordered = List[A]() def contains(elem: A): Boolean = containsEntry(elem) @@ -45,5 +52,6 @@ class LinkedHashSet[A] extends Set[A] with FlatHashTable[A] { super.clear() } override def clone(): Set[A] = new LinkedHashSet[A] ++ this - override def elements = ordered.reverse.elements + override def elements = Iterator.fromOld(ordered.reverse.elements) } + diff --git a/src/library/scala/collection/mutable/LinkedList.scala b/src/library/scala/collection/mutable/LinkedList.scala index 9765ae1f1e..8c8ebd3b0f 100644 --- a/src/library/scala/collection/mutable/LinkedList.scala +++ b/src/library/scala/collection/mutable/LinkedList.scala @@ -11,36 +11,27 @@ package scala.collection.mutable +import generic._ + /** This class implements single linked lists where both the head (<code>elem</code>) * and the tail (<code>next</code>) are mutable. * - * @author Matthias Zenger - * @version 1.0, 08/07/2003 + * @author Matthias Zenger + * @author Martin Odersky + * @version 2.8 */ @serializable -class LinkedList[A](var elem: A, var next: LinkedList[A]) - extends SingleLinkedList[A, LinkedList[A]] -{ - - /** Compares two lists structurally; i.e. checks if all elements - * contained in this list are also contained in the other list, - * and vice versa. - * - * @param that the other list - * @return <code>true</code> iff both lists contain exactly the - * same mappings. - */ - override def equals(obj: Any): Boolean = obj match { - case that: LinkedList[_] => this.toList equals that.toList - case _ => false - } - - /** A hash method compatible with <code>equals</code> - */ - override def hashCode(): Int = - (0 /: elements) ((hash, kv) => hash + kv.hashCode) - - override protected def stringPrefix: String = "LinkedList" +class LinkedList[A](_elem: A, _next: LinkedList[A]) extends LinearSequence[A] with LinkedListTemplate[A, LinkedList[A]] { + elem = _elem + next = _next + override protected[this] def newBuilder = LinkedList.newBuilder + override def traversibleBuilder[B]: Builder[B, LinkedList[B], Any] = LinkedList.newBuilder[B] +} + +object LinkedList extends SequenceFactory[LinkedList] { + type Coll = LinkedList[_] + implicit def builderFactory[A]: BuilderFactory[A, LinkedList[A], Coll] = new BuilderFactory[A, LinkedList[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, LinkedList[A], Any] = (new MutableList) mapResult ((l: MutableList[A]) => l.toLinkedList) } diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index 2fb8e39bdf..9374afc3db 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -11,144 +11,40 @@ package scala.collection.mutable - -import Predef._ +import generic._ +// import immutable.{List, Nil, ::} /** A Buffer implementation back up by a list. It provides constant time * prepend and append. Most other operations are linear. * * @author Matthias Zenger - * @version 1.0, 15/03/2004 + * @author Martin Odersky + * @version 2.8 */ @serializable -final class ListBuffer[A] extends Buffer[A] { +final class ListBuffer[A] + extends Buffer[A] + with BufferTemplate[A, ListBuffer[A]] + with Builder[A, List[A], Any] + with SequenceForwarder[A] +{ + import collection.Traversible + private var start: List[A] = Nil private var last0: ::[A] = _ private var exported: Boolean = false + private var len = 0 - /** Prepends a single element to this buffer. It takes constant - * time. - * - * @param x the element to prepend. - * @return this buffer. - */ - def +: (x: A): Buffer[A] = { - if (exported) copy() - val newElem = new scala.:: (x, start) - if (start.isEmpty) last0 = newElem - start = newElem - this - } - - - - /** Appends a single element to this buffer. It takes constant - * time. - * - * @param x the element to append. - */ - override def += (x: A) { - if (exported) copy() - if (start.isEmpty) { - last0 = new scala.:: (x, Nil) - start = last0 - } else { - val last1 = last0 - last0 = new scala.:: (x, Nil) - last1.tl = last0 - } - } - - /** Removes a single element from the buffer and return - * the identity of the buffer. Same as <code>this -= x; this</code>. It - * takes linear time (except removing the first element, which is done - * in constant time). - * - * @param x the element to remove. - * @return this buffer. - */ - def - (x: A): Buffer[A] = { this -= x; this } - - /** Remove a single element from this buffer. It takes linear time - * (except removing the first element, which is done in constant time). - * - * @param x the element to remove. - */ - override def -= (x: A) { - if (exported) copy() - if (start.isEmpty) {} - else if (start.head == x) start = start.tail - else { - var cursor = start - while (!cursor.tail.isEmpty && cursor.tail.head != x) { cursor = cursor.tail } - if (!cursor.tail.isEmpty) { - val z = cursor.asInstanceOf[scala.::[A]] - if (z.tl == last0) - last0 = z - z.tl = cursor.tail.tail - } - } - } - - /** Converts this buffer to a list. Takes constant time. The buffer is - * copied lazily, the first time it is mutated. - */ - override def toList: List[A] = { - exported = !start.isEmpty - start - } - /** expose the underlying list but do not mark it as exported */ - override def readOnly : List[A] = start + protected def underlying: immutable.Sequence[A] = start - /** Prepends the elements of this buffer to a given list - * - * @param xs the list to which elements are prepended - */ - def prependToList(xs: List[A]): List[A] = - if (start.isEmpty) xs - else { last0.tl = xs; toList } + override protected[this] def newBuilder = ListBuffer.newBuilder[A] + override def traversibleBuilder[B]: Builder[B, ListBuffer[B], Any] = ListBuffer.newBuilder[B] - /** Clears the buffer contents. + /** The current length of the buffer */ - def clear() { - start = Nil - exported = false - } + override def length = len - /** Copy contents of this buffer */ - private def copy() { - var cursor = start - val limit = last0.tail - clear - while (cursor ne limit) { - this += cursor.head - cursor = cursor.tail - } - } - - /** Returns the length of this buffer. It takes linear time. - * - * @return the length of this buffer. - */ - def length: Int = start.length - - // will be faster since this is a list - override def isEmpty = start.isEmpty - - /** Returns the n-th element of this list. This method - * yields an error if the element does not exist. Takes time - * linear in the buffer size. - * - * @param n the position of the element to be returned. - * @return the n-th element of this buffer. - * @throws Predef.IndexOutOfBoundsException - */ - def apply(n: Int): A = try { - start(n) - } catch { - case ex: Exception => - throw new IndexOutOfBoundsException(n.toString()) - } + // Implementations of abstract methods in Buffer /** Replaces element at index <code>n</code> with the new element * <code>newelem</code>. Takes time linear in the buffer size. (except the first @@ -162,8 +58,11 @@ final class ListBuffer[A] extends Buffer[A] { try { if (exported) copy() if (n == 0) { - val newElem = new scala.:: (x, start.tail); - if (last0 eq start) last0 = newElem + val newElem = new :: (x, start.tail); + if (last0 eq start) { + last0 = newElem + len += 1 + } start = newElem } else { var cursor = start @@ -172,15 +71,58 @@ final class ListBuffer[A] extends Buffer[A] { cursor = cursor.tail i += 1 } - val newElem = new scala.:: (x, cursor.tail.tail) - if (last0 eq cursor.tail) last0 = newElem - cursor.asInstanceOf[scala.::[A]].tl = newElem + val newElem = new :: (x, cursor.tail.tail) + if (last0 eq cursor.tail) { + last0 = newElem + len += 1 + } + cursor.asInstanceOf[::[A]].tl = newElem } } catch { case ex: Exception => throw new IndexOutOfBoundsException(n.toString()) } } + /** Appends a single element to this buffer. This operation takes constant time. + * + * @param x the element to append. + */ + def += (x: A) { + if (exported) copy() + if (start.isEmpty) { + last0 = new :: (x, Nil) + start = last0 + } else { + val last1 = last0 + last0 = new :: (x, Nil) + last1.tl = last0 + } + len += 1 + } + + /** Clears the buffer contents. + */ + def clear() { + start = Nil + exported = false + len = 0 + } + + /** Prepends a single element to this buffer. This operation takes constant + * time. + * + * @param x the element to prepend. + * @return this buffer. + */ + def +: (x: A): this.type = { + if (exported) copy() + val newElem = new :: (x, start) + if (start.isEmpty) last0 = newElem + start = newElem + len += 1 + this + } + /** Inserts new elements at the index <code>n</code>. Opposed to method * <code>update</code>, this method will not replace an element with a new * one. Instead, it will insert a new element at index <code>n</code>. @@ -189,13 +131,14 @@ final class ListBuffer[A] extends Buffer[A] { * @param iter the iterable object providing all elements to insert. * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds. */ - def insertAll(n: Int, iter: Iterable[A]) { + def insertAll(n: Int, seq: Traversible[A]) { try { if (exported) copy() - var elems = iter.elements.toList.reverse + var elems = seq.toList.reverse + len += elems.length if (n == 0) { while (!elems.isEmpty) { - val newElem = new scala.:: (elems.head, start) + val newElem = new :: (elems.head, start) if (start.isEmpty) last0 = newElem start = newElem elems = elems.tail @@ -208,9 +151,9 @@ final class ListBuffer[A] extends Buffer[A] { i += 1 } while (!elems.isEmpty) { - val newElem = new scala.:: (elems.head, cursor.tail) + val newElem = new :: (elems.head, cursor.tail) if (cursor.tail.isEmpty) last0 = newElem - cursor.asInstanceOf[scala.::[A]].tl = newElem + cursor.asInstanceOf[::[A]].tl = newElem elems = elems.tail } } @@ -220,9 +163,66 @@ final class ListBuffer[A] extends Buffer[A] { } } - /** Removes the element on a given index position. Takes time linear in - * the buffer size (except for the first element, which is removed in constant - * time). + /** Removes a given number of elements on a given index position. May take time linear in + * the buffer size. + * + * @param n the index which refers to the first element to remove. + * @param count the number of elements to remove. + */ + override def remove(n: Int, count: Int) { + if (exported) copy() + val n1 = n max 0 + val count1 = count min (len - n1) + var old = start.head; + if (n1 == 0) { + var c = count1 + while (c > 0) { + start = start.tail + c -= 1 + } + } else { + var cursor = start + var i = 1 + while (i < n1) { + cursor = cursor.tail + i += 1 + } + var c = count1 + while (c > 0) { + if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]] + cursor.asInstanceOf[::[A]].tl = cursor.tail.tail + c -= 1 + } + } + len -= count1 + } + +// Implementation of abstract method in Builder + + def result: List[A] = toList + + /** Converts this buffer to a list. Takes constant time. The buffer is + * copied lazily, the first time it is mutated. + */ + override def toList: List[A] = { + exported = !start.isEmpty + start + } + +// New methods in ListBuffer + + /** Prepends the elements of this buffer to a given list + * + * @param xs the list to which elements are prepended + */ + def prependToList(xs: List[A]): List[A] = + if (start.isEmpty) xs + else { last0.tl = xs; toList } + +// Overrides of methods in Buffer + + /** Removes the element on a given index position. May take time linear in + * the buffer size * * @param n the index which refers to the element to delete. * @return n the element that was formerly at position <code>n</code>. @@ -230,6 +230,7 @@ final class ListBuffer[A] extends Buffer[A] { * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds. */ def remove(n: Int): A = try { + if (n < 0 || n >= len) throw new IndexOutOfBoundsException(n.toString()) if (exported) copy() var old = start.head; if (n == 0) { @@ -242,27 +243,38 @@ final class ListBuffer[A] extends Buffer[A] { i += 1 } old = cursor.tail.head - if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[scala.::[A]] - cursor.asInstanceOf[scala.::[A]].tl = cursor.tail.tail + if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]] + cursor.asInstanceOf[::[A]].tl = cursor.tail.tail } + len -= 1 old - } catch { - case ex: Exception => - throw new IndexOutOfBoundsException(n.toString()) } - /** <p> - * Returns an iterator over all elements of this list. - * </p> - * <blockquote> - * Note: the iterator can be affected by insertions, updates and - * deletions that are performed afterwards on the buffer. To get - * iterator an over the current buffer snapshot, use - * <code>toList.elements</code>. - * </blockquote> + /** Remove a single element from this buffer. May take time linear in the buffer size. * - * @throws Predef.NoSuchElementException if buffer is empty + * @param x the element to remove. */ + override def -= (elem: A) { + if (exported) copy() + if (start.isEmpty) {} + else if (start.head == elem) { + start = start.tail + len -= 1 + } else { + var cursor = start + while (!cursor.tail.isEmpty && cursor.tail.head != elem) { + cursor = cursor.tail + } + if (!cursor.tail.isEmpty) { + val z = cursor.asInstanceOf[::[A]] + if (z.tl == last0) + last0 = z + z.tl = cursor.tail.tail + len -= 1 + } + } + } + override def elements = new Iterator[A] { var cursor: List[A] = null def hasNext: Boolean = !start.isEmpty && cursor != last0 @@ -275,31 +287,39 @@ final class ListBuffer[A] extends Buffer[A] { } } + /** expose the underlying list but do not mark it as exported */ + def readOnly: List[A] = start + + // Private methods + + /** Copy contents of this buffer */ + private def copy() { + var cursor = start + val limit = last0.tail + clear + while (cursor ne limit) { + this += cursor.head + cursor = cursor.tail + } + } + /** Returns a clone of this buffer. * * @return a <code>ListBuffer</code> with the same elements. */ - override def clone(): Buffer[A] = (new ListBuffer[A]) ++ this - - /** Checks if two buffers are structurally identical. - * - * @return <code>true</code>, iff both buffers contain the same sequence - * of elements. - */ - override def equals(obj: Any): Boolean = obj match { - case that: ListBuffer[_] => - (this.length == that.length && - elements.zip(that.elements).forall { - case (thiselem, thatelem) => thiselem == thatelem - }) - case _ => - false - } + override def clone(): ListBuffer[A] = (new ListBuffer[A]) ++ this /** Defines the prefix of the string representation. * * @return the string representation of this buffer. */ - override protected def stringPrefix: String = "ListBuffer" + override def stringPrefix: String = "ListBuffer" +} + +/* Factory object for `ListBuffer` class */ +object ListBuffer extends SequenceFactory[ListBuffer] { + type Coll = ListBuffer[_] + implicit def builderFactory[A]: BuilderFactory[A, ListBuffer[A], Coll] = new BuilderFactory[A, ListBuffer[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, ListBuffer[A], Any] = new AddingBuilder(new ListBuffer[A]) } diff --git a/src/library/scala/collection/mutable/Location.scala b/src/library/scala/collection/mutable/Location.scala index ff121b357e..cbe180f163 100644 --- a/src/library/scala/collection/mutable/Location.scala +++ b/src/library/scala/collection/mutable/Location.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -27,3 +28,4 @@ case object Start extends Location case object End extends Location case class Index(n: Int) extends Location +*/ diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala index 4c8fb7c1cd..cfa6ae5f1c 100644 --- a/src/library/scala/collection/mutable/Map.scala +++ b/src/library/scala/collection/mutable/Map.scala @@ -11,264 +11,35 @@ package scala.collection.mutable -import Predef._ - - -/** The canonical factory methods for <a href="Map.html">mutable maps</a>. - * These currently return <a href="HashMap.html">HashMap's</a>. +import generic._ + +trait Map[A, B] + extends Iterable[(A, B)] + with collection.Map[A, B] + with MutableMapTemplate[A, B, Map[A, B]] + with Unhashable { + + override def empty: Map[A, B] = Map.empty + override def mapBuilder[A, B]: Builder[(A, B), Map[A, B], Any] = Map.newBuilder[A, B] + + /** Return a read-only projection of this map. !!! or just use an (immutable) MapProxy? + def readOnly : collection.Map[A, B] = new collection.Map[A, B] { + override def size = self.size + override def update(key: A, value: B) = self.update(key, value) + override def - (elem: A) = self - elem + override def elements = self.elements + override def foreach(f: ((A, B)) => Unit) = self.foreach(f) + override def empty[C] = self.empty[C] + def get(key: A) = self.get(key) + } + */ +} +/* Factory object for `Map` class + * Currently this returns a HashMap. */ -object Map { - - /** The empty map of this type; this is implemented as a hashtable */ +object Map extends MutableMapFactory[Map] { + type Coll = Map[_, _] + implicit def builderFactory[A, B]: BuilderFactory[(A, B), Map[A, B], Coll] = new BuilderFactory[(A, B), Map[A, B], Coll] { def apply(from: Coll) = from.mapBuilder[A, B] } def empty[A, B]: Map[A, B] = new HashMap[A, B] - - /** The canonical factory for this type - */ - def apply[A, B](elems: (A, B)*) = empty[A, B] ++ elems } -/** This trait represents mutable maps. Concrete map implementations - * just have to provide functionality for the abstract methods in - * <code>scala.collection.Map</code> as well as for <code>update</code>, - * and <code>-=</code>. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.0, 31/12/2006 - */ -@cloneable -trait Map[A, B] extends AnyRef - with collection.Map[A, B] - with Scriptable[Message[(A, B)]] - with CloneableCollection -{ - /** This method allows one to add a new mapping from <code>key</code> - * to <code>value</code> to the map. If the map already contains a - * mapping for <code>key</code>, it will be overridden by this - * function. - * - * @param key The key to update - * @param value The new value - */ - def update(key: A, value: B) - - /** Add a key/value pair to this map. - * @param kv the key/value pair. - */ - def += (kv: (A, B)) { update(kv._1, kv._2) } - - /** Add two or more key/value pairs to this map. - * @param kv1 the first key/value pair. - * @param kv2 the second key/value pair. - * @param kvs the remaining key/value pairs. - */ - def += (kv1: (A, B), kv2: (A, B), kvs: (A, B)*) { - this += kv1; this += kv2; this ++= kvs - } - - /** Add a sequence of key/value pairs to this map. - * @param kvs the iterable object containing all key/value pairs. - */ - def ++= (kvs: Iterable[(A, B)]) { this ++= kvs.elements } - - /** Add a sequence of key/value pairs to this map. - * @param kvs the iterator containing all key/value pairs. - */ - def ++= (kvs: Iterator[(A, B)]) { kvs foreach += } - - /** Add a key/value pair to this map. - * @param kv the key/value pair. - * @return The map itself with the new binding added in place. - */ - def + (kv: (A, B)): Map[A, B] = { this += kv; this } - - /** Add two or more key/value pairs to this map. - * @param kv1 the first key/value pair. - * @param kv2 the second key/value pair. - * @param kvs the remaining key/value pairs. - * @return The map itself with the new bindings added in place. - */ - def + (kv1: (A, B), kv2: (A, B), kvs: (A, B)*): Map[A, B] = { - this.+=(kv1, kv2, kvs: _*); this - } - - /** Add a sequence of key/value pairs to this map. - * @param kvs the iterable object containing all key/value pairs. - * @return The itself map with the new bindings added in place. - */ - def ++ (kvs: Iterable[(A, B)]): Map[A, B] = { this ++= kvs; this } - - /** Add a sequence of key/value pairs to this map. - * @param kvs the iterator containing all key/value pairs. - * @return The itself map with the new bindings added in place. - */ - def ++ (kvs: Iterator[(A, B)]): Map[A, B] = { this ++= kvs; this } - - /** Remove a key from this map, noop if key is not present. - * @param key the key to be removed - */ - def -= (key: A) - - /** Remove two or more keys from this map - * @param key1 the first key to be removed - * @param key2 the second key to be removed - * @param keys the remaining keys to be removed - */ - def -= (key1: A, key2: A, keys: A*) { this -= key1; this -= key2; this --= keys } - - /** Remove a sequence of keys from this map - * @param keys the keys to be removed - */ - def --= (keys: Iterable[A]) { this --= keys.elements } - - /** Remove a sequence of keys from this map - * @param keys the keys to be removed - */ - def --= (keys: Iterator[A]) { keys foreach -= } - - /** Remove a key from this map - * @param key the key to be removed - * @return The map itself with the binding for <code>key</code> removed if - * it existed. - */ - def - (key: A): Map[A, B] = { this -= key; this } - - /** Remove <code>key</code> from this map and return the element - * that the key was previously mapped to (if any). - */ - def removeKey(key: A): Option[B] = { - val ret = get(key) - this -= key - ret - } - - /** Map <code>key</code> to <code>elem</code> in this map and return the element - * that the key was previously mapped to (if any). - */ - def put(key: A, elem: B): Option[B] = { - val ret = get(key) - this(key) = elem - ret - } - - /** Remove two or more keys from this map - * @param key1 the first key to be removed - * @param key2 the second key to be removed - * @param keys the remaining keys to be removed - * @return The map itself with all bindings for the given keys removed. - */ - def - (key1: A, key2: A, keys: A*): Map[A, B] = { this.-=(key1, key2, keys: _*); this } - - /** Remove a sequence of keys from this map - * @param keys the keys to be removed - * @return The map itself with all bindings for <code>keys</code> removed. - */ - def -- (keys: Iterable[A]): Map[A, B] = { this --= keys; this } - - /** Remove a sequence of keys from this map - * @param keys the keys to be removed - * @return The map itself with all bindings for <code>keys</code> removed. - */ - def -- (keys: Iterator[A]): Map[A, B] = { this --= keys; this } - - /** Removes all mappings from the map. After this operation is - * completed, the map is empty. - */ - def clear() { keys foreach -= } - - /** Check if this map maps <code>key</code> to a value. - * Return that value if it exists, otherwise put <code>default</code> - * as that key's value and return it. - */ - def getOrElseUpdate(key: A, default: => B): B = - get(key) match { - case Some(v) => v - case None => val d = default; this(key) = d; d - } - - /** This function transforms all the values of mappings contained - * in this map with function <code>f</code>. - * - * @param f The transformation to apply - */ - def transform(f: (A, B) => B) { - elements foreach { - case (key, value) => update(key, f(key, value)) - } - } - - /** This method retains only those mappings for which the predicate - * <code>p</code> returns <code>true</code>. - * - * @param p The test predicate - * @deprecated cannot be type inferred because if retain in Iterable. - */ - def retain(p: (A, B) => Boolean) { - toList foreach { - case (key, value) => if (!p(key, value)) -=(key) - } - } - - /** Send a message to this scriptable object. - * - * @param cmd the message to send. - */ - def <<(cmd: Message[(A, B)]): Unit = cmd match { - case Include((k, v)) => update(k, v) - case Update((k, v)) => update(k, v) - case Remove((k, _)) => this -= k - case Reset() => clear - case s: Script[_] => s.elements foreach << - case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") - } - - /** Return a clone of this map. - * - * @return a map with the same elements. - */ - override def clone(): Map[A, B] = super.clone().asInstanceOf[Map[A, B]] - - /** Return a read-only projection of this map */ - def readOnly: scala.collection.Map[A, B] = new scala.collection.Map[A, B] { - override def toString = "ro-" + Map.this.toString - override def size = Map.this.size - override def elements = Map.this.elements - override def get(key: A) = Map.this.get(key) - } - - /** This method defines syntactic sugar for adding or modifying - * mappings. It is typically used in the following way: - * <pre> - * map += key -> value - * </pre> - * @deprecated use <code>+= Pair(key, value)</code> - */ - @deprecated - def +=(key: A): MapTo = new MapTo(key) - - /** <code>incl</code> can be used to add many mappings at the same time - * to the map. The method assumes that a mapping is represented - * by a <code>Pair</code> object who's first component denotes the - * key, and who's second component refers to the value. - * - * @param mappings - * @deprecated use <code>+=</code> - */ - @deprecated - def incl(mappings: (A, B)*) { this ++= mappings.elements } - - /** This method will remove all the mappings for the given sequence - * of keys from the map. - * - * @param keys - * @deprecated use <code>-=</code> - */ - @deprecated - def excl(keys: A*) { this --= keys.elements } - - @deprecated - class MapTo(key: A) { - def ->(value: B) { update(key, value) } - } - -} diff --git a/src/library/scala/collection/mutable/MapProxy.scala b/src/library/scala/collection/mutable/MapProxy.scala index 228b9daac3..a215702f19 100644 --- a/src/library/scala/collection/mutable/MapProxy.scala +++ b/src/library/scala/collection/mutable/MapProxy.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -55,3 +56,4 @@ trait MapProxy[A, B] extends Map[A, B] with collection.MapProxy[A, B] { @deprecated override def excl(keys: A*): Unit = self.excl(keys: _*) } +*/ diff --git a/src/library/scala/collection/mutable/Message.scala b/src/library/scala/collection/mutable/Message.scala index 1874a1d3b7..7b5ad7b2a0 100644 --- a/src/library/scala/collection/mutable/Message.scala +++ b/src/library/scala/collection/mutable/Message.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -80,3 +81,4 @@ class Script[A] extends ArrayBuffer[Message[A]] with Message[A] { override def hashCode(): Int = throw new UnsupportedOperationException("scripts are not suitable as hash keys") } +*/ diff --git a/src/library/scala/collection/mutable/MultiMap.scala b/src/library/scala/collection/mutable/MultiMap.scala index 297568872e..7f7a8e9b07 100644 --- a/src/library/scala/collection/mutable/MultiMap.scala +++ b/src/library/scala/collection/mutable/MultiMap.scala @@ -17,23 +17,30 @@ package scala.collection.mutable * <code>B</code> objects. * * @author Matthias Zenger - * @version 1.0, 08/07/2003 + * @author Martin Odersky + * @version 2.8 */ trait MultiMap[A, B] extends Map[A, Set[B]] { protected def makeSet: Set[B] = new HashSet[B] - def add(key: A, value: B): Unit = get(key) match { - case None => - val set = makeSet - set += value - this(key) = set - case Some(set) => - set += value + def addBinding(key: A, value: B): this.type = { + get(key) match { + case None => + val set = makeSet + set += value + this(key) = set + case Some(set) => + set += value + } + this } - def remove(key: A, value: B) = get(key) match { - case None => - case Some(set) => set -= value + def removeBinding(key: A, value: B): this.type = { + get(key) match { + case None => + case Some(set) => set -= value + } + this } def entryExists(key: A, p: B => Boolean): Boolean = get(key) match { diff --git a/src/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala index b4f6e59a33..c2ef583b98 100644 --- a/src/library/scala/collection/mutable/MutableList.scala +++ b/src/library/scala/collection/mutable/MutableList.scala @@ -11,36 +11,63 @@ package scala.collection.mutable +import generic._ +// import immutable.{List, Nil, ::} //import Predef.NoSuchElementException /** This class is used internally to represent mutable lists. It is the - * basis for the implementation of the classes <code>Buffer</code>, + * basis for the implementation of the classes * <code>Stack</code>, and <code>Queue</code>. - * + * !!! todo: convert to LinkedListBuffer? * @author Matthias Zenger - * @version 1.0, 08/07/2003 + * @author Martin Odersky + * @version 2.8 */ -trait MutableList[A] extends Seq[A] with PartialFunction[Int, A] { +class MutableList[A] extends LinearSequence[A] with LinearSequenceTemplate[A, MutableList[A]] with Builder[A, MutableList[A], Any] { + + override protected[this] def newBuilder = new MutableList[A] protected var first0: LinkedList[A] = null protected var last0: LinkedList[A] = null protected var len: Int = 0 - /** Returns the length of this list. + /** Is the list empty? + */ + override def isEmpty = len == 0 + + /** Returns the first element in this list */ - def length: Int = len + override def head: A = first0.head - /** Returns the <code>n</code>th element of this list. This method - * yields an error if the element does not exist. + /** Returns the rest of this list */ - def apply(n: Int): A = get(n) match { - case None => throw new NoSuchElementException("element not found") - case Some(value) => value + override def tail: MutableList[A] = { + val tl = new MutableList[A] + if (first0 ne last0) { + tl.first0 = first0.tail + tl.last0 = last0 + } + tl.len = len - 1 + tl } + /** Returns the length of this list. + */ + override def length: Int = len + + /** Returns the <code>n</code>th element of this list. + * @throws IndexOutofBoundsException if index does not exist. + */ + override def apply(n: Int): A = first0.apply(n) + + /** Updates the <code>n</code>th element of this list to a new value. + * @throws IndexOutofBoundsException if index does not exist. + */ + def update(n: Int, x: A): Unit = first0.update(n, x) + /** Returns the <code>n</code>th element of this list or <code>None</code> - * if this element does not exist. + * if index does not exist. */ def get(n: Int): Option[A] = first0.get(n) @@ -60,16 +87,13 @@ trait MutableList[A] extends Seq[A] with PartialFunction[Int, A] { len = len + 1 } - protected def reset() { - first0 = null - last0 = null - len = 0 - } + /** @deprecated use clear instead */ + @deprecated def reset() { clear() } /** Returns an iterator over all elements of this list. */ override def elements: Iterator[A] = - if (first0 eq null) Nil.elements else first0.elements + if (first0 eq null) Iterator.empty else first0.elements override def last = last0.elem @@ -78,5 +102,22 @@ trait MutableList[A] extends Seq[A] with PartialFunction[Int, A] { */ override def toList: List[A] = if (first0 eq null) Nil else first0.toList - override protected def stringPrefix: String = "MutableList" + /** Returns the current list of elements as a linked List + * sequence of elements. + */ + private[mutable] def toLinkedList: LinkedList[A] = first0 + + /** Appends a single element to this buffer. This takes constant time. + * + * @param elem the element to append. + */ + def +=(elem: A) = appendElem(elem) + + def clear() { + first0 = null + last0 = null + len = 0 + } + + def result = this } diff --git a/src/library/scala/collection/mutable/ObservableBuffer.scala b/src/library/scala/collection/mutable/ObservableBuffer.scala index cc39c4180c..40e8bf3641 100644 --- a/src/library/scala/collection/mutable/ObservableBuffer.scala +++ b/src/library/scala/collection/mutable/ObservableBuffer.scala @@ -1,4 +1,5 @@ -/* __ *\ +/* TODO: Reintegrate +* /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | ** @@ -80,3 +81,4 @@ trait ObservableBuffer[A, This <: ObservableBuffer[A, This]] }) } } +*/ diff --git a/src/library/scala/collection/mutable/ObservableMap.scala b/src/library/scala/collection/mutable/ObservableMap.scala index d86caf715d..1fd5c0dbca 100644 --- a/src/library/scala/collection/mutable/ObservableMap.scala +++ b/src/library/scala/collection/mutable/ObservableMap.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -56,3 +57,4 @@ trait ObservableMap[A, B, This <: ObservableMap[A, B, This]] }) } } +*/ diff --git a/src/library/scala/collection/mutable/ObservableSet.scala b/src/library/scala/collection/mutable/ObservableSet.scala index a9b30fb18c..6885c368fd 100644 --- a/src/library/scala/collection/mutable/ObservableSet.scala +++ b/src/library/scala/collection/mutable/ObservableSet.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -43,3 +44,4 @@ trait ObservableSet[A, This <: ObservableSet[A, This]] }) } } +*/ diff --git a/src/library/scala/collection/mutable/OpenHashMap.scala b/src/library/scala/collection/mutable/OpenHashMap.scala index b0b35960e2..f4ae7204aa 100644 --- a/src/library/scala/collection/mutable/OpenHashMap.scala +++ b/src/library/scala/collection/mutable/OpenHashMap.scala @@ -18,6 +18,8 @@ object OpenHashMap{ dict; } + def empty[K, V] = new OpenHashMap[K, V]; + private[mutable] class Entry[Key, Value](val key : Key, val hash : Int, var value : Option[Value]) @@ -48,6 +50,8 @@ import OpenHashMap.Entry; class OpenHashMap[Key, Value](initialSize : Int) extends scala.collection.mutable.Map[Key, Value]{ def this() = this(8); + override def empty = OpenHashMap.empty + private[this] val actualInitialSize = OpenHashMap.nextPowerOfTwo(initialSize); private var mask = actualInitialSize - 1;; @@ -58,7 +62,7 @@ class OpenHashMap[Key, Value](initialSize : Int) extends scala.collection.mutabl // Used for tracking inserts so that iterators can determine in concurrent modification has occurred. private[this] var modCount = 0; - def size = _size; + override def size = _size; private[this] def size_=(s : Int) = _size = s; protected def hashOf(key : Key) = { @@ -200,12 +204,15 @@ class OpenHashMap[Key, Value](initialSize : Int) extends scala.collection.mutabl private[this] def foreachUndeletedEntry(f : Entry[Key, Value] => Unit){ table.foreach(entry => if (entry != null && entry.value != None) f(entry)); } - - override def transform(f : (Key, Value) => Value) = + override def transform(f : (Key, Value) => Value) = { foreachUndeletedEntry(entry => entry.value = Some(f(entry.key, entry.value.get))); + this + } - override def retain(f : (Key, Value) => Boolean) = + override def retain(f : (Key, Value) => Boolean) = { foreachUndeletedEntry(entry => if (!f(entry.key, entry.value.get)) {entry.value = None; size -= 1; deleted += 1} ); + this + } override def stringPrefix = "OpenHashMap" } diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala index 1a3d1c2f56..70dfd56fff 100644 --- a/src/library/scala/collection/mutable/PriorityQueue.scala +++ b/src/library/scala/collection/mutable/PriorityQueue.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -195,3 +196,4 @@ class PriorityQueue[A <% Ordered[A]] extends ResizableArray[A] with CloneableCol res } } +*/ diff --git a/src/library/scala/collection/mutable/PriorityQueueProxy.scala b/src/library/scala/collection/mutable/PriorityQueueProxy.scala index 47e4bbd9ad..7eab4df05e 100644 --- a/src/library/scala/collection/mutable/PriorityQueueProxy.scala +++ b/src/library/scala/collection/mutable/PriorityQueueProxy.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -98,3 +99,4 @@ abstract class PriorityQueueProxy[A <% Ordered[A]] extends PriorityQueue[A] def self = PriorityQueueProxy.this.self.clone() } } +*/ diff --git a/src/library/scala/collection/mutable/Publisher.scala b/src/library/scala/collection/mutable/Publisher.scala index 2a5e05b48e..77c9dff282 100644 --- a/src/library/scala/collection/mutable/Publisher.scala +++ b/src/library/scala/collection/mutable/Publisher.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -46,3 +47,4 @@ trait Publisher[A, This <: Publisher[A, This]] { self: This => filters.keys.foreach(sub => if (filters.entryExists(sub, p => p(event))) sub.notify(this, event)) } +*/ diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala index 2bda38481c..f4fcab4abf 100644 --- a/src/library/scala/collection/mutable/Queue.scala +++ b/src/library/scala/collection/mutable/Queue.scala @@ -11,6 +11,7 @@ package scala.collection.mutable +import generic._ //import Predef.{NoSuchElementException, UnsupportedOperationException} @@ -18,44 +19,17 @@ package scala.collection.mutable * insert and retrieve elements in a first-in-first-out (FIFO) manner. * * @author Matthias Zenger - * @version 1.1, 03/05/2004 + * @author Martin Odersky + * @version 2.8 */ @serializable @cloneable -class Queue[A] extends MutableList[A] with CloneableCollection { - - /** Checks if the queue is empty. - * - * @return true, iff there is no element in the queue. - */ - override def isEmpty: Boolean = (first0 eq null) - - /** Inserts a single element at the end of the queue. - * - * @param elem the element to insert - */ - def +=(elem: A): Unit = appendElem(elem) - - /** Adds all elements provided by an <code>Iterable</code> object - * at the end of the queue. The elements are prepended in the order they - * are given out by the iterator. - * - * @param iter an iterable object - */ - def ++=(iter: Iterable[A]): Unit = this ++= iter.elements - - /** Adds all elements provided by an iterator - * at the end of the queue. The elements are prepended in the order they - * are given out by the iterator. - * - * @param it an iterator - */ - def ++=(it: Iterator[A]): Unit = it foreach appendElem +class Queue[A] extends MutableList[A] with Cloneable[Queue[A]] { /** Adds all elements to the queue. * * @param elems the elements to add. */ - def enqueue(elems: A*): Unit = (this ++= elems) + def enqueue(elems: A*): Unit = (this ++= collection.Iterable.fromOld(elems)) /** Returns the first element in the queue, and removes this element * from the queue. @@ -106,9 +80,9 @@ class Queue[A] extends MutableList[A] with CloneableCollection { * @return a sequence of all elements in the queue for which * p yields true. */ - def dequeueAll(p: A => Boolean): Seq[A] = { + def dequeueAll(p: A => Boolean): Sequence[A] = { if (first0 eq null) - Seq.empty + Sequence.empty else { val res = new ArrayBuffer[A] while ((first0 ne null) && p(first0.elem)) { @@ -156,47 +130,4 @@ class Queue[A] extends MutableList[A] with CloneableCollection { * @return the first element. */ def front: A = first0.elem - - /** Removes all elements from the queue. After this operation is completed, - * the queue will be empty. - */ - def clear(): Unit = reset - - /** Checks if two queues are structurally identical. - * - * @return true, iff both queues contain the same sequence of elements. - */ - override def equals(obj: Any): Boolean = obj match { - case that: Queue[_] => - (this.elements zip that.elements) forall { - case (thiselem, thatelem) => thiselem == thatelem - } - case _ => - false - } - - /** The hashCode method always yields an error, since it is not - * safe to use mutable queues as keys in hash tables. - * - * @throws Predef.UnsupportedOperationException - * @return never. - */ - override def hashCode(): Int = - throw new UnsupportedOperationException("unsuitable as hash key") - - /** Returns a textual representation of a queue as a string. - * - * @return the string representation of this queue. - */ - override def toString() = toList.mkString("Queue(", ", ", ")") - - /** This method clones the queue. - * - * @return a queue with the same elements. - */ - override def clone(): Queue[A] = { - val res = new Queue[A] - res ++= this - res - } } diff --git a/src/library/scala/collection/mutable/QueueProxy.scala b/src/library/scala/collection/mutable/QueueProxy.scala index 8480671b0b..cfe364108a 100644 --- a/src/library/scala/collection/mutable/QueueProxy.scala +++ b/src/library/scala/collection/mutable/QueueProxy.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -99,3 +100,4 @@ trait QueueProxy[A] extends Queue[A] with SeqProxy[A] { def self = QueueProxy.this.self.clone() } } +*/ diff --git a/src/library/scala/collection/mutable/ResizableArray.scala b/src/library/scala/collection/mutable/ResizableArray.scala index dc34ba87c0..1d260cc275 100644 --- a/src/library/scala/collection/mutable/ResizableArray.scala +++ b/src/library/scala/collection/mutable/ResizableArray.scala @@ -11,37 +11,43 @@ package scala.collection.mutable -import Predef._ +import generic._ /** This class is used internally to implement data structures that * are based on resizable arrays. - * //todo enrich with more efficient operations * * @author Matthias Zenger, Burak Emir - * @version 1.0, 03/05/2004 + * @author Martin Odersky + * @version 2.8 */ -trait ResizableArray[A] extends RandomAccessSeq[A] { +trait ResizableArray[A] extends Vector[A] with VectorTemplate[A, ResizableArray[A]] { self => + + import scala.Array // !!! + import collection.Iterable // !!! + + override protected[this] def newBuilder = ResizableArray.newBuilder + override def traversibleBuilder[B]: Builder[B, ResizableArray[B], Any] = ResizableArray.newBuilder[B] protected def initialSize: Int = 16 - protected var array: Array[AnyRef] = new Array[AnyRef](initialSize min 1) - private var size1: Int = 0 - protected def size0: Int = size1 - protected def size0_=(sz: Int) { size1 = sz } + protected var array: Array[AnyRef] = new Array[AnyRef](initialSize max 1) + + protected var size0: Int = 0 //########################################################################## - // implement/override methods of Seq[A] + // implement/override methods of Vector[A] /** Returns the length of this resizable array. */ def length: Int = size0 - def apply(i: Int) = array(i).asInstanceOf[A] + def apply(idx: Int) = { + if (idx >= size0) throw new IndexOutOfBoundsException(idx.toString) + array(idx).asInstanceOf[A] + } - /** remove elements of this array at indices after <code>sz</code> - */ - def reduceToSize(sz: Int) { - if (sz > size0) throw new IllegalArgumentException - size0 = sz + def update(idx: Int, elem: A) { + if (idx >= size0) throw new IndexOutOfBoundsException(idx.toString) + array(idx) = elem.asInstanceOf[AnyRef] } /** Fills the given array <code>xs</code> with the elements of @@ -56,25 +62,35 @@ trait ResizableArray[A] extends RandomAccessSeq[A] { /** Copy all elements to a buffer * @param The buffer to which elements are copied - */ override def copyToBuffer[B >: A](dest: Buffer[B]) { - dest.++=(runtime.ScalaRunTime.boxArray(array).asInstanceOf[Array[B]], 0, size0) + dest ++= (array: Sequence[AnyRef]).asInstanceOf[Sequence[B]] } - - /** Returns a new iterator over all elements of this resizable array. */ - override def elements: Iterator[A] = new Iterator[A] { + + override def foreach(f: A => Unit) { var i = 0 - def hasNext: Boolean = i < size0 - def next(): A = { i = i + 1; array(i - 1).asInstanceOf[A] } + while (i < size) { + f(array(i).asInstanceOf[A]) + i += 1 + } } //########################################################################## + /** remove elements of this array at indices after <code>sz</code> + */ + def reduceToSize(sz: Int) { + require(sz <= size0) + while (size0 > sz) { + size0 -= 1 + array(size0) = null + } + } + /** ensure that the internal array has at n cells */ protected def ensureSize(n: Int) { if (n > array.length) { - var newsize = if (array.length == 0) 2 else array.length * 2 + var newsize = array.length * 2 while (n > newsize) newsize = newsize * 2 val newar: Array[AnyRef] = new Array(newsize) @@ -97,3 +113,9 @@ trait ResizableArray[A] extends RandomAccessSeq[A] { Array.copy(array, m, array, n, len) } } + +object ResizableArray extends SequenceFactory[ResizableArray] { + type Coll = Vector[_] + implicit def builderFactory[A]: BuilderFactory[A, Vector[A], Coll] = new BuilderFactory[A, Vector[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, ResizableArray[A], Any] = new ArrayBuffer[A] +} diff --git a/src/library/scala/collection/mutable/RevertableHistory.scala b/src/library/scala/collection/mutable/RevertibleHistory.scala index 0996eb64c8..6561a74c2c 100644..100755 --- a/src/library/scala/collection/mutable/RevertableHistory.scala +++ b/src/library/scala/collection/mutable/RevertibleHistory.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -6,7 +7,7 @@ ** |/ ** \* */ -// $Id$ +// $Id: RevertableHistory.scala 16893 2009-01-13 13:09:22Z cunei $ package scala.collection.mutable @@ -31,3 +32,4 @@ class RevertableHistory[A <: Undoable, B] extends History[A, B] with Undoable { old.foreach { case (sub, event) => event.undo } } } +*/ diff --git a/src/library/scala/collection/mutable/Scriptable.scala b/src/library/scala/collection/mutable/Scriptable.scala index 0a9b9b8525..f2341d4e4f 100644 --- a/src/library/scala/collection/mutable/Scriptable.scala +++ b/src/library/scala/collection/mutable/Scriptable.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -24,3 +25,4 @@ trait Scriptable[A] { */ def <<(cmd: A): Unit } +*/ diff --git a/src/library/scala/collection/mutable/Sequence.scala b/src/library/scala/collection/mutable/Sequence.scala new file mode 100755 index 0000000000..01293924ac --- /dev/null +++ b/src/library/scala/collection/mutable/Sequence.scala @@ -0,0 +1,27 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.collection.mutable + +import generic._ + +/** A subtrait of collection.Sequence which represents sequences + * that can be mutated. + * The class adds an `update` method to collection.Sequence. + */ +trait Sequence[A] extends Iterable[A] with collection.Sequence[A] with SequenceTemplate[A, Sequence[A]] with Unhashable { + override protected[this] def newBuilder = Sequence.newBuilder + override def traversibleBuilder[B]: Builder[B, Sequence[B], Any] = Sequence.newBuilder[B] + + def update(idx: Int, elem: A) +} + +object Sequence extends SequenceFactory[Sequence] { + type Coll = Sequence[_] + implicit def builderFactory[A]: BuilderFactory[A, Sequence[A], Coll] = new BuilderFactory[A, Sequence[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Sequence[A], Any] = new ArrayBuffer +} diff --git a/src/library/scala/collection/mutable/Set.scala b/src/library/scala/collection/mutable/Set.scala index 7bc6be9292..d75b816564 100644 --- a/src/library/scala/collection/mutable/Set.scala +++ b/src/library/scala/collection/mutable/Set.scala @@ -11,21 +11,7 @@ package scala.collection.mutable -import Predef._ - - -/** The canonical factory methods for <a href="Set.html">mutable sets</a>. - * Currently these return <a href="HashSet.html">HashSet's</a>. - */ -object Set { - - /** The empty map of this type; this is implemented as a hashtable */ - def empty[A]: Set[A] = new HashSet[A] - - /** The canonical factory for this type - */ - def apply[A](elems: A*) = empty[A] ++ elems -} +import generic._ /** This class represents mutable sets. Concrete set implementations * just have to provide functionality for the abstract methods in @@ -33,11 +19,22 @@ object Set { * <code>scala.collection.Set</code></a> as well as for <code>+=</code>, * <code>-= and <code>clear</code>. * - * @author Matthias Zenger - * @version 1.1, 09/05/2004 + * @author Matthias Zenger + * @author Martin Odersky + * @version 2.8 */ -@cloneable -trait Set[A] extends collection.Set[A] with Scriptable[Message[A]] with CloneableCollection { +trait Set[A] extends Iterable[A] + with collection.Set[A] + with SetTemplate[A, Set[A]] + with Growable[A] + with Shrinkable[A] + with Cloneable[Set[A]] + with Unhashable { +self => + + override def empty = Set.empty + + override def traversibleBuilder[B]: Builder[B, Set[B], Any] = Set.newBuilder[B] /** This method allows one to add or remove an element <code>elem</code> * from this set depending on the value of parameter <code>included</code>. @@ -49,168 +46,69 @@ trait Set[A] extends collection.Set[A] with Scriptable[Message[A]] with Cloneabl if (included) this += elem else this -= elem } - /** Add a new element to the set. + /** Adds a new element to the set. * * @param elem the element to be added */ def +=(elem: A) - /** Add two or more elements to this set. - * @param elem1 the first element. - * @param elem2 the second element. - * @param elems the remaining elements. - */ - def += (elem1: A, elem2: A, elems: A*) { this += elem1; this += elem2; this ++= elems } - - /** Add all the elements provided by an iterator - * of the iterable object <code>that</code> to the set. - * @param elems the iterable object containing the elements to be added - */ - def ++=(elems: Iterable[A]): Unit = ++=(elems.elements) - - /** Add all the elements provided by an iterator - * <code>elems</code> to the set. - * @param elems the iterator containing the elements to be added - */ - def ++=(elems: Iterator[A]) { elems foreach += } - - /** Add a new element to the set. - * @return the set itself with the element added. - * - * @param elem the element to be added - */ - def + (elem: A): Set[A] = { +=(elem); this } - - /** Add two or more elements to this set. - * @param elem1 the first element. - * @param kv2 the second element. - * @param kvs the remaining elements. - * @return the set itself with the elements added. - */ - def + (elem1: A, elem2: A, elems: A*): Set[A] = { this.+=(elem1, elem2, elems: _*); this } - - /** Add all the elements provided by an iterator - * of the iterable object <code>elems</code> to the set. - * - * @param elems the iterable object containing the elements to be added - * @return the set itself with the elements added. - */ - def ++ (elems: Iterable[A]): Set[A] = { this ++= elems; this } - - /** Add all the elements provided by an iterator - * <code>elems</code> to the set. - * @param elems the iterator containing the elements to be added - */ - def ++ (elems: Iterator[A]): Set[A] = { this ++= elems; this } - - /** <code>incl</code> can be used to add many elements to the set - * at the same time. - * @deprecated use <code>++=</code> instead - */ - @deprecated - def incl(elems: A*): Unit = ++=(elems.elements) - /** Removes a single element from a set. * @param elem The element to be removed. */ def -=(elem: A) - /** Remove two or more elements from this set. - * @param elem1 the first element. - * @param elem2 the second element. - * @param elems the remaining elements. - */ - def -= (elem1: A, elem2: A, elems: A*) { this -= elem1; this -= elem2; this --= elems } - - /** Remove all the elements provided by an iterator - * of the iterable object <code>elems</code> from the set. - */ - def --=(elems: Iterable[A]): Unit = --=(elems.elements) - - /** Remove all the elements provided by an iterator - * <code>elems</code> from the set. - */ - def --=(elems: Iterator[A]) { elems foreach -= } - - /** Remove a new element from the set. - * @return the set itself with the element removed. + /** Adds a new element to the set and returns the set itself. * - * @param elem the element to be removed - */ - def - (elem: A): Set[A] = { -=(elem); this } - - /** Remove two or more elements from this set. - * @param elem1 the first element. - * @param elem2 the second element. - * @param elems the remaining elements. - * @return the set itself with the elements removed. + * @param elem the element to be added */ - def - (elem1: A, elem2: A, elems: A*): Set[A] = { this.-=(elem1, elem2, elems: _*); this } + override def +(elem: A): this.type = { +=(elem); this } - /** Remove all the elements provided by an iterator - * of the iterable object <code>elems</code> from the set. + /** Removed a new element from the set and returns the set itself. * - * @param elems An iterable object containing the elements to remove from the set. - * @return the set itself with the elements removed. - */ - def -- (elems: Iterable[A]): Set[A] = { this --= elems; this } - - /** Remove all the elements provided by an iterator - * <code>elems</code> from the set. - * @param elems An iterator containing the elements to remove from the set. - * @return the set itself with the elements removed. - */ - def -- (elems: Iterator[A]): Set[A] = { this --= elems; this } - - /** <code>excl</code> removes many elements from the set. + * @param elem the element to be added */ - @deprecated - def excl(elems: A*): Unit = --=(elems.elements) + override def -(elem: A): this.type = { -=(elem); this } /** This method computes an intersection with set <code>that</code>. * It removes all the elements that are not present in <code>that</code>. * * @param that the set to intersect with. */ - def intersect(that: Set[A]) { retain(that.contains) } + override def intersect(that: collection.Set[A]): this.type = { retain(that.contains); this } /** Method <code>retain removes all elements from the set for * which the predicate <code>p</code> yields the value <code>false</code>. */ - def retain(p: A => Boolean): Unit = toList.foreach { - elem => if (!p(elem)) -=(elem) - } + def retain(p: A => Boolean): Unit = for (elem <- this.toList) if (!p(elem)) this -= elem /** Removes all elements from the set. After this operation is completed, * the set will be empty. */ - def clear() { elements foreach -= } + def clear() { foreach(-=) } + + override def clone(): Set[A] = { val b = newBuilder; b ++= this; b.result } /** Send a message to this scriptable object. * * @param cmd the message to send. * @throws <code>Predef.UnsupportedOperationException</code> * if the message was not understood. - */ - def <<(cmd: Message[A]): Unit = cmd match { + def <<(cmd: Message[A]): Unit = cmd match { case Include(elem) => this += elem case Remove(elem) => this -= elem case Reset() => clear case s: Script[_] => s.elements foreach << case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") } + */ +} - /** Return a clone of this set. - * - * @return a set with the same elements. - */ - override def clone(): Set[A] = super.clone().asInstanceOf[Set[A]] - - /** Return a read-only projection of this set */ - def readOnly : scala.collection.Set[A] = new scala.collection.Set[A] { - def contains(item : A) = Set.this.contains(item) - override def toString = "ro-" + Set.this.toString - override def size = Set.this.size - override def elements = Set.this.elements - } +/** The canonical factory methods for <a href="Set.html">mutable sets</a>. + * Currently this returns a HashSet. + */ +object Set extends SetFactory[Set] { + type Coll = Set[_] + implicit def builderFactory[A]: BuilderFactory[A, Set[A], Coll] = new BuilderFactory[A, Set[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def empty[A]: Set[A] = HashSet.empty[A] } + diff --git a/src/library/scala/collection/mutable/SetProxy.scala b/src/library/scala/collection/mutable/SetProxy.scala index 0e693b7302..e13f18691b 100644 --- a/src/library/scala/collection/mutable/SetProxy.scala +++ b/src/library/scala/collection/mutable/SetProxy.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -54,3 +55,4 @@ trait SetProxy[A] extends Set[A] with collection.SetProxy[A] { def self = SetProxy.this.self.clone() } } +*/ diff --git a/src/library/scala/collection/mutable/SingleLinkedList.scala b/src/library/scala/collection/mutable/SingleLinkedList.scala deleted file mode 100644 index ac07066432..0000000000 --- a/src/library/scala/collection/mutable/SingleLinkedList.scala +++ /dev/null @@ -1,62 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.collection.mutable - -/** This extensible class may be used as a basis for implementing linked - * list. Type variable <code>A</code> refers to the element type of the - * list, type variable <code>This</code> is used to model self types of - * linked lists. - * - * @author Matthias Zenger - * @version 1.0, 08/07/2003 - */ -abstract class SingleLinkedList[A, This >: Null <: SingleLinkedList[A, This]] - extends AnyRef with Seq[A] -{ self: This => - - var elem: A - - var next: This - - def length: Int = 1 + (if (next eq null) 0 else next.length) - - def append(that: This): Unit = - if (next eq null) next = that else next.append(that) - - def insert(that: This): Unit = if (that ne null) { - that.append(next) - next = that - } - - def apply(n: Int): A = - if (n == 0) elem - else if (next eq null) throw new IndexOutOfBoundsException("unknown element") - else next.apply(n - 1) - - def get(n: Int): Option[A] = - if (n == 0) Some(elem) - else if (next eq null) None - else next.get(n - 1) - - override def elements: Iterator[A] = new Iterator[A] { - var elems = SingleLinkedList.this - def hasNext = (elems ne null) - def next = { - val res = elems.elem - elems = elems.next - res; - } - } - - override def toList: List[A] = elements toList - -} diff --git a/src/library/scala/collection/mutable/Stack.scala b/src/library/scala/collection/mutable/Stack.scala index 2faf1964c8..0d554e01da 100644 --- a/src/library/scala/collection/mutable/Stack.scala +++ b/src/library/scala/collection/mutable/Stack.scala @@ -11,57 +11,70 @@ package scala.collection.mutable +import generic._ /** A stack implements a data structure which allows to store and retrieve * objects in a last-in-first-out (LIFO) fashion. * * @author Matthias Zenger - * @version 1.1, 03/05/2004 + * @author Martin Odersky + * @version 2.8 */ @serializable @cloneable -class Stack[A] extends Seq[A] with CloneableCollection { - private var stack: immutable.Stack[A] = immutable.Stack.Empty +class Stack[A] private (var elems: List[A]) extends collection.Sequence[A] with Cloneable[Stack[A]] { + + def this() = this(Nil) /** Checks if the stack is empty. * * @return true, iff there is no element on the stack */ - override def isEmpty: Boolean = stack.isEmpty + override def isEmpty: Boolean = elems.isEmpty - override def length = stack.length + /** The number of elements in the stack */ + override def length = elems.length - override def apply(index: Int) = stack(index) + /** Retrieve n'th element from stack, where top of stack has index 0 */ + override def apply(index: Int) = elems(index) - /** Pushes a single element on top of the stack. + /** Push an element on the stack. * - * @param elem the element to push onto the stack + * @param elem the element to push on the stack. + * @return the stack with the new element on top. */ - def +=(elem: A) { - this push elem - } + def push(elem: A): this.type = { elems = elem :: elems; this } - /** Pushes all elements provided by an <code>Iterable</code> object - * on top of the stack. The elements are pushed in the order they - * are given out by the iterator. + /** Push two or more elements onto the stack. The last element + * of the sequence will be on top of the new stack. * - * @param iter an iterable object + * @param elems the element sequence. + * @return the stack with the new elements on top. */ - def ++=(iter: Iterable[A]): Unit = stack = stack ++ iter + def push(elem1: A, elem2: A, elems: A*): this.type = this.push(elem1).push(elem2).pushAll(elems) - /** Pushes all elements provided by an iterator - * on top of the stack. The elements are pushed in the order they - * are given out by the iterator. + /** Push all elements provided by the given iterator object onto + * the stack. The last element returned by the iterator + * will be on top of the new stack. * - * @param iter an iterator + * @param elems the iterator object. + * @return the stack with the new elements on top. + * @deprecated */ - def ++=(it: Iterator[A]): Unit = stack = stack ++ it + def pushAll(elems: Iterator[A]): this.type = { for (elem <- elems) { push(elem); () }; this } - /** Pushes a sequence of elements on top of the stack. The first element - * is pushed first, etc. + /** Push all elements provided by the given iterable object onto + * the stack. The last element returned by the traversible object + * will be on top of the new stack. * - * @param elems a sequence of elements + * @param elems the iterable object. + * @return the stack with the new elements on top. */ - def push(elems: A*): Unit = (this ++= elems) + def pushAll(elems: collection.Traversible[A]): this.type = { for (elem <- elems) { push(elem); () }; this } + + /** @deprecated use pushAll */ + @deprecated def ++=(it: Iterator[A]): Unit = pushAll(it) + /** @deprecated use pushAll */ + @deprecated def ++=(it: Iterable[A]): Unit = pushAll(it) /** Returns the top element of the stack. This method will not remove * the element from the stack. An error is signaled if there is no @@ -71,7 +84,7 @@ class Stack[A] extends Seq[A] with CloneableCollection { * @return the top element */ def top: A = - stack.top + elems.head /** Removes the top element from the stack. * @@ -79,8 +92,8 @@ class Stack[A] extends Seq[A] with CloneableCollection { * @return the top element */ def pop(): A = { - val res = stack.top - stack = stack.pop + val res = elems.head + elems = elems.tail res } @@ -88,52 +101,27 @@ class Stack[A] extends Seq[A] with CloneableCollection { * Removes all elements from the stack. After this operation completed, * the stack will be empty. */ - def clear(): Unit = stack = immutable.Stack.Empty + def clear(): Unit = elems = Nil /** Returns an iterator over all elements on the stack. This iterator * is stable with respect to state changes in the stack object; i.e. * such changes will not be reflected in the iterator. The iterator - * issues elements in the order they were inserted into the stack - * (FIFO order). + * issues elements in the reversed order they were inserted into the stack + * (LIFO order). * * @return an iterator over all stack elements. */ - override def elements: Iterator[A] = stack.elements + override def elements: Iterator[A] = elems.elements - /** Creates a list of all stack elements in FIFO order. + /** Creates a list of all stack elements in LIFO order. * * @return the created list. */ - override def toList: List[A] = stack.toList - - /** Checks if two stacks are structurally identical. - * - * @return true, iff both stacks contain the same sequence of elements. - */ - override def equals(obj: Any): Boolean = obj match { - case that: Stack[_] => - this.stack == that.stack - case _ => - false - } - - /** The hashCode method always yields an error, since it is not - * safe to use mutable stacks as keys in hash tables. - * - * @return never. - */ - override def hashCode(): Int = - throw new UnsupportedOperationException("unsuitable as hash key") + override def toList: List[A] = elems /** This method clones the stack. * * @return a stack with the same elements. */ - override def clone(): Stack[A] = { - val res = new Stack[A] - res ++= this - res - } - - override protected def stringPrefix: String = "Stack" + override def clone(): Stack[A] = new Stack[A](elems) } diff --git a/src/library/scala/collection/mutable/StackProxy.scala b/src/library/scala/collection/mutable/StackProxy.scala index 2fedc50542..1833af0f33 100644 --- a/src/library/scala/collection/mutable/StackProxy.scala +++ b/src/library/scala/collection/mutable/StackProxy.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -109,3 +110,4 @@ trait StackProxy[A] extends Stack[A] with SeqProxy[A] { def self = StackProxy.this.self.clone() } } +*/ diff --git a/src/library/scalax/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala index 386f316f27..d70261f84b 100755 --- a/src/library/scalax/collection/mutable/StringBuilder.scala +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -9,17 +9,16 @@ // $Id: StringBuilder.scala 16884 2009-01-09 16:52:09Z cunei $ -package scalax.collection.mutable - -import scalax.collection.generic._ -import scalax.runtime._ +package scala.collection.mutable +import collection.generic._ +import scala.runtime.RichString /** <p> * A mutable sequence of characters. This class provides an API compatible * with <a class="java/lang/StringBuilder" href="" target="_top"> * <code>java.lang.StringBuilder</code></a>. - * </p> + * </p>generic/ * * @author Stephane Micheloud * @author Martin Odersky @@ -28,12 +27,10 @@ import scalax.runtime._ @serializable @SerialVersionUID(0 - 8525408645367278351L) final class StringBuilder(initCapacity: Int, private val initValue: String) - extends PartialFunction[Int, Char] - with Growable[Any] - with java.lang.CharSequence { - require(initCapacity > 0) + extends Builder[Char, String, Any] + with Vector[Char] { - type Array[T] = scala.Array[T] // !!! + require(initCapacity > 0) /** The value is used for character storage. */ private var array = new Array[Char](initCapacity + initValue.length) @@ -147,10 +144,6 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) /** Same as <code>charAt</code>. */ def apply(i: Int): Char = charAt(i) - /** Does builder contain an element at given index `idx`? - */ - def isDefinedAt(i: Int): Boolean = 0 <= i && i < count - /** <p> * Removes the <code>Char</code> at the specified position in this * sequence. This sequence is shortened by one <code>Char</code>. @@ -233,7 +226,10 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) /* Appends the string representation of the <code>Any</code> argument. */ - def +=(x: Any) { append(x) } + def +=(x: Char) { append(x) } + + def +(x: Char): this.type = { +=(x); this } + /** <p> * Appends the string representation of the <code>Any</code> @@ -367,7 +363,7 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) * @param x a <code>Boolean</code>. * @return a reference to this object. */ - def append(x: Boolean): StringBuilder = append(String.valueOf(this)) + def append(x: Boolean): StringBuilder = append(String.valueOf(x)) def append(x: Byte): StringBuilder = append(String.valueOf(x)) def append(x: Char): StringBuilder = { @@ -807,7 +803,7 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) * * @return a reference to this object. */ - def reverse(): StringBuilder = { + override def reverse(): StringBuilder = { var hasSurrogate = false val n = count - 1 var j = (n-1) >> 1 @@ -816,8 +812,8 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) val temp2 = array(n - j) if (!hasSurrogate) hasSurrogate = - (temp >= Character.MIN_HIGH_SURROGATE && temp <= Character.MAX_LOW_SURROGATE) || - (temp2 >= Character.MIN_HIGH_SURROGATE && temp2 <= Character.MAX_LOW_SURROGATE) + (temp >= StringBuilder.MIN_SURROGATE && temp <= StringBuilder.MAX_SURROGATE) || + (temp2 >= StringBuilder.MIN_SURROGATE && temp2 <= StringBuilder.MAX_SURROGATE) array(j) = temp2 array(n - j) = temp j -= 1 @@ -827,9 +823,9 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) var i = 0 while (i < count - 1) { val c2 = array(i) - if (Character.isLowSurrogate(c2)) { + if (StringBuilder.isLowSurrogate(c2)) { val c1 = array(i + 1) - if (Character.isHighSurrogate(c1)) { + if (StringBuilder.isHighSurrogate(c1)) { array(i) = c1; i += 1 array(i) = c2 } @@ -849,7 +845,9 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) * * @return a string representation of this sequence of characters. */ - override def toString(): String = new String(array, 0, count) + override def toString: String = new String(array, 0, count) + + def result(): String = toString } @@ -857,6 +855,23 @@ object StringBuilder { type Array[T] = scala.Array[T] // !!! + private val MIN_HIGH_SURROGATE = '\uD800' + private val MAX_HIGH_SURROGATE = '\uDBFF' + + private val MIN_LOW_SURROGATE = '\uDC00' + private val MAX_LOW_SURROGATE = '\uDFFF' + + // constants <code>java.langCharacter.MIN-/MAX_SURROGATE</code> exist since 1.5 + private val MIN_SURROGATE = MIN_HIGH_SURROGATE + private val MAX_SURROGATE = MAX_LOW_SURROGATE + + // methods <code>java.langCharacter.isLow-/isHighSurrogate</code> exist since 1.5 + private def isLowSurrogate(ch: Char): Boolean = + MIN_LOW_SURROGATE <= ch && ch <= MAX_LOW_SURROGATE + + private def isHighSurrogate(ch: Char): Boolean = + MIN_HIGH_SURROGATE <= ch && ch <= MAX_HIGH_SURROGATE + // method <code>java.util.Arrays.copyOf</code> exists since 1.6 private def copyOf(src: Array[Char], newLength: Int): Array[Char] = { val dest = new Array[Char](newLength) diff --git a/src/library/scala/collection/mutable/Subscriber.scala b/src/library/scala/collection/mutable/Subscriber.scala index 751fe12498..c3d5723660 100644 --- a/src/library/scala/collection/mutable/Subscriber.scala +++ b/src/library/scala/collection/mutable/Subscriber.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -23,3 +24,4 @@ package scala.collection.mutable trait Subscriber[-A, -B] { def notify(pub: B, event: A): Unit } +*/ diff --git a/src/library/scala/collection/mutable/SynchronizedBuffer.scala b/src/library/scala/collection/mutable/SynchronizedBuffer.scala index 199c44db67..03978d9d71 100644 --- a/src/library/scala/collection/mutable/SynchronizedBuffer.scala +++ b/src/library/scala/collection/mutable/SynchronizedBuffer.scala @@ -20,6 +20,8 @@ package scala.collection.mutable */ trait SynchronizedBuffer[A] extends Buffer[A] { + import collection.Traversible + abstract override def length: Int = synchronized { super.length } @@ -55,7 +57,7 @@ trait SynchronizedBuffer[A] extends Buffer[A] { * * @param iter the iterable object. */ - override def ++(iter: Iterable[A]): Buffer[A] = synchronized { + override def ++(iter: Traversible[A]): Buffer[A] = synchronized { super.++(iter) } @@ -64,7 +66,7 @@ trait SynchronizedBuffer[A] extends Buffer[A] { * * @param iter the iterable object. */ - override def ++=(iter: Iterable[A]): Unit = synchronized { + override def ++=(iter: Traversible[A]): Unit = synchronized { super.++=(iter) } @@ -81,7 +83,7 @@ trait SynchronizedBuffer[A] extends Buffer[A] { * * @param iter the iterable object. */ - override def appendAll(iter: Iterable[A]): Unit = synchronized { + override def appendAll(iter: Traversible[A]): Unit = synchronized { super.appendAll(iter) } @@ -100,7 +102,7 @@ trait SynchronizedBuffer[A] extends Buffer[A] { * * @param iter the iterable object. */ - override def ++:(iter: Iterable[A]): Buffer[A] = synchronized { + override def ++:(iter: Traversible[A]): Buffer[A] = synchronized { super.++:(iter) } @@ -118,7 +120,7 @@ trait SynchronizedBuffer[A] extends Buffer[A] { * * @param iter the iterable object. */ - override def prependAll(elems: Iterable[A]): Unit = synchronized { + override def prependAll(elems: Traversible[A]): Unit = synchronized { super.prependAll(elems) } @@ -140,7 +142,7 @@ trait SynchronizedBuffer[A] extends Buffer[A] { * @param n the index where a new element will be inserted. * @param iter the iterable object providing all elements to insert. */ - abstract override def insertAll(n: Int, iter: Iterable[A]): Unit = synchronized { + abstract override def insertAll(n: Int, iter: Traversible[A]): Unit = synchronized { super.insertAll(n, iter) } @@ -167,11 +169,11 @@ trait SynchronizedBuffer[A] extends Buffer[A] { abstract override def clear(): Unit = synchronized { super.clear } - +/* TODO: Reintegrate override def <<(cmd: Message[(Location, A)]): Unit = synchronized { super.<<(cmd) } - +*/ /** Return a clone of this buffer. * * @return an <code>ArrayBuffer</code> with the same elements. diff --git a/src/library/scala/collection/mutable/SynchronizedMap.scala b/src/library/scala/collection/mutable/SynchronizedMap.scala index 450eaa5814..6ca07f4fa5 100644 --- a/src/library/scala/collection/mutable/SynchronizedMap.scala +++ b/src/library/scala/collection/mutable/SynchronizedMap.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -20,6 +21,10 @@ package scala.collection.mutable */ trait SynchronizedMap[A, B] extends Map[A, B] { + import collection.Traversible + + override def mapBuilder[A, B]: Builder[(A, B), SynchronizedMap[A, B], Any] = SynchronizedMap.newBuilder[A, B] + abstract override def size: Int = synchronized { super.size } @@ -81,7 +86,7 @@ trait SynchronizedMap[A, B] extends Map[A, B] { super.+=(kv1, kv2, kvs: _*) } - override def ++=(map: Iterable[(A, B)]): Unit = synchronized { + override def ++=(map: Traversible[(A, B)]): Unit = synchronized { super.++=(map) } @@ -89,11 +94,6 @@ trait SynchronizedMap[A, B] extends Map[A, B] { super.++=(it) } - @deprecated - override def incl(mappings: (A, B)*): Unit = synchronized { - super.incl(mappings: _*) - } - abstract override def -=(key: A): Unit = synchronized { super.-=(key) } @@ -102,7 +102,7 @@ trait SynchronizedMap[A, B] extends Map[A, B] { super.-=(key1, key2, keys: _*) } - override def --=(keys: Iterable[A]): Unit = synchronized { + override def --=(keys: Traversible[A]): Unit = synchronized { super.--=(keys) } @@ -110,24 +110,19 @@ trait SynchronizedMap[A, B] extends Map[A, B] { super.--=(it) } - @deprecated - override def excl(keys: A*): Unit = synchronized { - super.excl(keys: _*) - } - override def clear(): Unit = synchronized { super.clear } - +/* TODO: Reintegrate override def getOrElseUpdate(key: A, default: => B): B = synchronized { super.getOrElseUpdate(key, default) } - - override def transform(f: (A, B) => B): Unit = synchronized { +*/ + override def transform(f: (A, B) => B): this.type = synchronized[this.type] { super.transform(f) } - override def retain(p: (A, B) => Boolean): Unit = synchronized { + override def retain(p: (A, B) => Boolean): this.type = synchronized[this.type] { super.retain(p) } @@ -139,15 +134,23 @@ trait SynchronizedMap[A, B] extends Map[A, B] { super.equals(that) } - override def hashCode(): Int = synchronized { - super.hashCode() - } - +/* TODO: Reintegrate override def <<(cmd: Message[(A, B)]): Unit = synchronized { super.<<(cmd) } - +*/ override def clone(): Map[A, B] = synchronized { super.clone() } } + +/* Factory object for `Map` class + * Currently this returns a HashMap. + */ +object SynchronizedMap extends MutableMapFactory[SynchronizedMap] { + type Coll = Map[_, _] + implicit def implicitBuilder[A, B]: Builder[(A, B), Map[A, B], Coll] = from.mapBuilder[A, B] + def empty[A, B]: Map[A, B] = new HashMap[A, B] with SynchronizeddMap[A, B] +} + +*/ diff --git a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala index 3c8bbfe5aa..f500b46aa0 100644 --- a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala +++ b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -84,16 +85,10 @@ class SynchronizedPriorityQueue[A <% Ordered[A]] extends PriorityQueue[A] { */ override def equals(that: Any): Boolean = synchronized { super.equals(that) } - /** The hashCode method always yields an error, since it is not - * safe to use mutable queues as keys in hash tables. - * - * @return never. - */ - override def hashCode(): Int = synchronized { super.hashCode() } - /** Returns a textual representation of a queue as a string. * * @return the string representation of this queue. */ override def toString(): String = synchronized { super.toString() } } +*/ diff --git a/src/library/scala/collection/mutable/SynchronizedQueue.scala b/src/library/scala/collection/mutable/SynchronizedQueue.scala index b31ab5e5dd..7ef88e867f 100644 --- a/src/library/scala/collection/mutable/SynchronizedQueue.scala +++ b/src/library/scala/collection/mutable/SynchronizedQueue.scala @@ -20,6 +20,7 @@ package scala.collection.mutable * @version 1.0, 03/05/2004 */ class SynchronizedQueue[A] extends Queue[A] { + import collection.Traversible /** Checks if the queue is empty. * @@ -39,7 +40,7 @@ class SynchronizedQueue[A] extends Queue[A] { * * @param iter an iterable object */ - override def ++=(iter: Iterable[A]): Unit = synchronized { super.++=(iter) } + override def ++=(iter: Traversible[A]): Unit = synchronized { super.++=(iter) } /** Adds all elements provided by an iterator * at the end of the queue. The elements are prepended in the order they @@ -80,13 +81,6 @@ class SynchronizedQueue[A] extends Queue[A] { */ override def equals(that: Any): Boolean = synchronized { super.equals(that) } - /** The hashCode method always yields an error, since it is not - * safe to use mutable queues as keys in hash tables. - * - * @return never. - */ - override def hashCode(): Int = synchronized { super.hashCode() } - /** Returns a textual representation of a queue as a string. * * @return the string representation of this queue. diff --git a/src/library/scala/collection/mutable/SynchronizedSet.scala b/src/library/scala/collection/mutable/SynchronizedSet.scala index 8003e5a262..f355e5879d 100644 --- a/src/library/scala/collection/mutable/SynchronizedSet.scala +++ b/src/library/scala/collection/mutable/SynchronizedSet.scala @@ -19,6 +19,7 @@ package scala.collection.mutable * @version 1.0, 08/07/2003 */ trait SynchronizedSet[A] extends Set[A] { + import collection.Traversible abstract override def size: Int = synchronized { super.size @@ -40,7 +41,7 @@ trait SynchronizedSet[A] extends Set[A] { super.+=(elem) } - override def ++=(that: Iterable[A]) = synchronized { + override def ++=(that: Traversible[A]) = synchronized { super.++=(that) } @@ -48,15 +49,11 @@ trait SynchronizedSet[A] extends Set[A] { super.++=(it) } - override def incl(elems: A*): Unit = synchronized { - super.++=(elems) - } - abstract override def -=(elem: A): Unit = synchronized { super.-=(elem) } - override def --=(that: Iterable[A]) = synchronized { + override def --=(that: Traversible[A]) = synchronized { super.--=(that) } @@ -64,11 +61,7 @@ trait SynchronizedSet[A] extends Set[A] { super.--=(it) } - override def excl(elems: A*): Unit = synchronized { - super.--=(elems) - } - - override def intersect(that: Set[A]) = synchronized { + override def intersect(that: collection.Set[A]) = synchronized[this.type] { super.intersect(that) } @@ -96,10 +89,11 @@ trait SynchronizedSet[A] extends Set[A] { super.toString } +/* TODO: Reintegrate override def <<(cmd: Message[A]): Unit = synchronized { super.<<(cmd) } - +*/ override def clone(): Set[A] = synchronized { super.clone() } diff --git a/src/library/scala/collection/mutable/SynchronizedStack.scala b/src/library/scala/collection/mutable/SynchronizedStack.scala index 572e689f9c..6d90f6a531 100644 --- a/src/library/scala/collection/mutable/SynchronizedStack.scala +++ b/src/library/scala/collection/mutable/SynchronizedStack.scala @@ -20,6 +20,7 @@ package scala.collection.mutable * @version 1.0, 03/05/2004 */ class SynchronizedStack[A] extends Stack[A] { + import collection.Traversible /** Checks if the stack is empty. * @@ -31,30 +32,31 @@ class SynchronizedStack[A] extends Stack[A] { * * @param elem the element to push onto the stack */ - override def +=(elem: A): Unit = synchronized { super.+=(elem) } + override def push(elem: A): this.type = synchronized[this.type] { super.push(elem) } - /** Pushes all elements provided by an <code>Iterable</code> object + /** Push two or more elements onto the stack. The last element + * of the sequence will be on top of the new stack. + * + * @param elems the element sequence. + * @return the stack with the new elements on top. + */ + override def push(elem1: A, elem2: A, elems: A*): this.type = synchronized[this.type] { super.push(elem1, elem2, elems: _*) } + + /** Pushes all elements provided by an <code>Traversible</code> object * on top of the stack. The elements are pushed in the order they * are given out by the iterator. * * @param iter an iterable object */ - override def ++=(iter: Iterable[A]): Unit = synchronized { super.++=(iter) } + override def pushAll(elems: collection.Traversible[A]): this.type = synchronized[this.type] { super.pushAll(elems) } /** Pushes all elements provided by an iterator * on top of the stack. The elements are pushed in the order they * are given out by the iterator. * - * @param iter an iterator - */ - override def ++=(it: Iterator[A]): Unit = synchronized { super.++=(it) } - - /** Pushes a sequence of elements on top of the stack. The first element - * is pushed first, etc. - * - * @param elems a sequence of elements + * @param elems an iterator */ - override def push(elems: A*): Unit = synchronized { super.++=(elems) } + override def pushAll(elems: Iterator[A]): this.type = synchronized[this.type] { super.pushAll(elems) } /** Returns the top element of the stack. This method will not remove * the element from the stack. An error is signaled if there is no @@ -90,19 +92,6 @@ class SynchronizedStack[A] extends Stack[A] { */ override def toList: List[A] = synchronized { super.toList } - /** Checks if two stacks are structurally identical. - * - * @return true, iff both stacks contain the same sequence of elements. - */ - override def equals(that: Any): Boolean = synchronized { super.equals(that) } - - /** The hashCode method always yields an error, since it is not - * safe to use mutable stacks as keys in hash tables. - * - * @return never. - */ - override def hashCode(): Int = synchronized { super.hashCode() } - /** Returns a textual representation of a stack as a string. * * @return the string representation of this stack. diff --git a/src/library/scala/collection/mutable/Traversible.scala b/src/library/scala/collection/mutable/Traversible.scala new file mode 100755 index 0000000000..b177c9ca5d --- /dev/null +++ b/src/library/scala/collection/mutable/Traversible.scala @@ -0,0 +1,30 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.collection.mutable + +import generic._ + +/** A subtrait of collection.Traversible which represents traversibles + * that can be mutated. + * + * @autor Martin Odersky + * @version 2.8 + */ +trait Traversible[A] extends collection.Traversible[A] with TraversibleTemplate[A, Traversible[A]] with Mutable { self => + override protected[this] def newBuilder = Traversible.newBuilder + override def traversibleBuilder[B]: Builder[B, Traversible[B], Any] = Traversible.newBuilder[B] +} + +/* A factory object for the trait `Traversible` */ +object Traversible extends TraversibleFactory[Traversible] { + type Coll = Traversible[_] + implicit def builderFactory[A]: BuilderFactory[A, Traversible[A], Coll] = new BuilderFactory[A, Traversible[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Traversible[A], Any] = new ArrayBuffer +} + + diff --git a/src/library/scala/collection/mutable/Undoable.scala b/src/library/scala/collection/mutable/Undoable.scala index 21d23fb887..5e0f4b8e76 100644 --- a/src/library/scala/collection/mutable/Undoable.scala +++ b/src/library/scala/collection/mutable/Undoable.scala @@ -1,3 +1,4 @@ +/* TODO: Reintegrate /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** @@ -24,3 +25,4 @@ trait Undoable { */ def undo() } +*/ diff --git a/src/library/scala/collection/mutable/Vector.scala b/src/library/scala/collection/mutable/Vector.scala new file mode 100755 index 0000000000..a253f4b64f --- /dev/null +++ b/src/library/scala/collection/mutable/Vector.scala @@ -0,0 +1,24 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.collection.mutable + +import generic._ + +/** A subtrait of collection.Vector which represents sequences + * that can be mutated. + */ +trait Vector[A] extends Sequence[A] with collection.Vector[A] with MutableVectorTemplate[A, Vector[A]] { + override protected[this] def newBuilder = Vector.newBuilder + override def traversibleBuilder[B]: Builder[B, Vector[B], Any] = Vector.newBuilder[B] +} + +object Vector extends SequenceFactory[Vector] { + type Coll = Vector[_] + implicit def builderFactory[A]: BuilderFactory[A, Vector[A], Coll] = new BuilderFactory[A, Vector[A], Coll] { def apply(from: Coll) = from.traversibleBuilder[A] } + def newBuilder[A]: Builder[A, Vector[A], Any] = new ArrayBuffer +} diff --git a/src/library/scalax/collection/Map.scala b/src/library/scala/collection/mutable/WeakHashMap.scala index 602da06bb0..7520026e01 100755..100644 --- a/src/library/scalax/collection/Map.scala +++ b/src/library/scala/collection/mutable/WeakHashMap.scala @@ -6,16 +6,13 @@ ** |/ ** \* */ -// $Id: Map.scala 16884 2009-01-09 16:52:09Z cunei $ +// $Id: Symbol.scala 17537 2009-04-20 18:37:37Z odersky $ -package scalax.collection +package scala.collection.mutable -import generic._ +import JavaConversions._ -trait Map[A, B] extends MapTemplate[A, B, Map] - -/* Factory object for `Map` class */ -object Map extends MapFactory[Map] { - def empty[A, B]: Map[A, B] = new immutable.EmptyMap[A, B] +class WeakHashMap[A, B] extends JMapWrapper[A, B](new java.util.WeakHashMap) { + override def empty = new WeakHashMap[A, B] } diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala new file mode 100755 index 0000000000..d4130b3920 --- /dev/null +++ b/src/library/scala/package.scala @@ -0,0 +1,34 @@ +package object scala { + type Iterable[+A] = scala.collection.Iterable[A] + val Iterable = scala.collection.Iterable + + /** @deprecated use Iterable instead */ + @deprecated type Collection[+A] = Iterable[A] + /** @deprecated use Iterable instead */ + @deprecated val Collection = Iterable + + type Seq[+A] = scala.collection.Sequence[A] + val Seq = scala.collection.Sequence + + type RandomAccessSeq[+A] = scala.collection.Vector[A] + val RandomAccessSeq = scala.collection.Vector + + type Iterator[+A] = scala.collection.Iterator[A] + val Iterator = scala.collection.Iterator + + type BufferedIterator[+A] = scala.collection.BufferedIterator[A] + + type List[+A] = scala.collection.immutable.List[A] + val List = scala.collection.immutable.List + + val Nil = scala.collection.immutable.Nil + + type ::[A] = scala.collection.immutable.::[A] + val :: = scala.collection.immutable.:: + + type Stream[+A] = scala.collection.immutable.Stream[A] + val Stream = scala.collection.immutable.Stream + + type StringBuilder = scala.collection.mutable.StringBuilder + val StringBuilder = scala.collection.mutable.StringBuilder +} diff --git a/src/library/scalax/runtime/Boxed.scala b/src/library/scala/runtime/Boxed.scala index 241b12e485..5a43eba80a 100644..100755 --- a/src/library/scalax/runtime/Boxed.scala +++ b/src/library/scala/runtime/Boxed.scala @@ -9,7 +9,7 @@ // $Id: Buffer.scala 15799 2008-08-15 18:23:54Z odersky $ -package scalax.runtime +package scala.runtime trait Boxed { diff --git a/src/library/scala/runtime/BoxedAnyArray.scala b/src/library/scala/runtime/BoxedAnyArray.scala index b30f2f2d24..42fd4c53bb 100644 --- a/src/library/scala/runtime/BoxedAnyArray.scala +++ b/src/library/scala/runtime/BoxedAnyArray.scala @@ -11,8 +11,6 @@ package scala.runtime - -import Predef._ import compat.Platform /** @@ -24,54 +22,8 @@ import compat.Platform @serializable final class BoxedAnyArray[A](val length: Int) extends BoxedArray[A] { -/* - def this(dim1: Int, dim2: Int) = { - this(dim1); - initializeWith(i => new BoxedAnyArray(dim2)) - } - - def this(dim1: Int, dim2: Int, dim3: Int) = { - this(dim1); - initializeWith(i => new BoxedAnyArray(dim2, dim3)) - } - - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int) = { - this(dim1); - initializeWith(i => new BoxedAnyArray(dim2, dim3, dim4)) - } - - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int) = { - this(dim1); - initializeWith(i => new BoxedAnyArray(dim2, dim3, dim4, dim5)) - } - - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int) = { - this(dim1); - initializeWith(i => new BoxedAnyArray(dim2, dim3, dim4, dim5, dim6)) - } - - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int) = { - this(dim1); - initializeWith(i => new BoxedAnyArray(dim2, dim3, dim4, dim5, dim6, dim7)) - } - - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int) = { - this(dim1); - initializeWith(i => new BoxedAnyArray(dim2, dim3, dim4, dim5, dim6, dim7, dim8)) - } - - def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int, dim9: Int) = { - this(dim1); - initializeWith(i => new BoxedAnyArray(dim2, dim3, dim4, dim5, dim6, dim7, dim8, dim9)) - } - - private def initializeWith(elem: Int => Any) = { - for (i <- 0 until length) update(i, elem(i)) - } -*/ - private var boxed = new Array[AnyRef](length) - private val hash = boxed.hashCode() +// private val hash = boxed.hashCode() private var unboxed: AnyRef = null private var elemClass: Class[_] = null @@ -122,17 +74,6 @@ final class BoxedAnyArray[A](val length: Int) extends BoxedArray[A] { unboxed.asInstanceOf[Array[AnyRef]](index) = elem } - def unbox(elemTag: String): AnyRef = - if (elemTag eq ScalaRunTime.IntTag) unbox(classOf[Int]) - else if (elemTag eq ScalaRunTime.DoubleTag) unbox(classOf[Double]) - else if (elemTag eq ScalaRunTime.FloatTag) unbox(classOf[Float]) - else if (elemTag eq ScalaRunTime.LongTag) unbox(classOf[Long]) - else if (elemTag eq ScalaRunTime.CharTag) unbox(classOf[Char]) - else if (elemTag eq ScalaRunTime.ByteTag) unbox(classOf[Byte]) - else if (elemTag eq ScalaRunTime.ShortTag) unbox(classOf[Short]) - else if (elemTag eq ScalaRunTime.BooleanTag) unbox(classOf[Boolean]) - else unbox(Platform.getClassForName(elemTag)) - def unbox(elemClass: Class[_]): AnyRef = synchronized { if (unboxed eq null) { this.elemClass = elemClass; @@ -201,7 +142,6 @@ final class BoxedAnyArray[A](val length: Int) extends BoxedArray[A] { } unboxed = newvalue; } else if (elemClass == classOf[AnyRef]) { - // todo: replace with ScalaRunTime.AnyRef.class unboxed = boxed } else { unboxed = Platform.createArray(elemClass, length) @@ -222,11 +162,13 @@ final class BoxedAnyArray[A](val length: Int) extends BoxedArray[A] { unboxed } +/* !!! todo: deal with array equality override def equals(other: Any): Boolean = other.isInstanceOf[BoxedAnyArray[_]] && (this eq (other.asInstanceOf[BoxedAnyArray[_]])) || (if (unboxed eq null) boxed == other else unboxed == other) override def hashCode(): Int = hash +*/ def value: AnyRef = { if (unboxed eq null) throw new NotDefinedError("BoxedAnyArray.value") @@ -246,21 +188,21 @@ final class BoxedAnyArray[A](val length: Int) extends BoxedArray[A] { case that: BoxedArray[_] => adapt(that.value) case that: Array[Int] => - unbox(ScalaRunTime.IntTag); that + unbox(classOf[Int]); that case that: Array[Double] => - unbox(ScalaRunTime.DoubleTag); that + unbox(classOf[Double]); that case that: Array[Float] => - unbox(ScalaRunTime.FloatTag); that + unbox(classOf[Float]); that case that: Array[Long] => - unbox(ScalaRunTime.LongTag); that + unbox(classOf[Long]); that case that: Array[Char] => - unbox(ScalaRunTime.CharTag); that + unbox(classOf[Char]); that case that: Array[Short] => - unbox(ScalaRunTime.ShortTag); that + unbox(classOf[Short]); that case that: Array[Byte] => - unbox(ScalaRunTime.ByteTag); that + unbox(classOf[Byte]); that case that: Array[Boolean] => - unbox(ScalaRunTime.BooleanTag); that + unbox(classOf[Boolean]); that case _ => other } @@ -286,34 +228,12 @@ final class BoxedAnyArray[A](val length: Int) extends BoxedArray[A] { Array.copy(if (unboxed ne null) unboxed else boxed, from, dest1, to, len) } - override def subArray(start: Int, end: Int): AnyRef = { - val result = new BoxedAnyArray(end - start); - Array.copy(this, start, result, 0, end - start) - result - } - final override def filter(p: A => Boolean): BoxedArray[A] = { - val include = new Array[Boolean](length) - var len = 0 - var i = 0 - while (i < length) { - if (p(this(i))) { include(i) = true; len += 1 } - i += 1 - } + val (len, include) = countAndMemo(p) val result = new BoxedAnyArray[A](len) - len = 0 - i = 0 - while (len < result.length) { - if (include(i)) { result(len) = this(i); len += 1 } - i += 1 - } - result - } - override protected def newArray(length : Int, elements : Iterator[A]) = { - val result = new BoxedAnyArray[A](length) - var i = 0 - while (elements.hasNext) { - result(i) = elements.next + var i, j = 0 + while (j < len) { + if (include(i)) { result(j) = this(i); j += 1 } i += 1 } result diff --git a/src/library/scala/runtime/BoxedArray.scala b/src/library/scala/runtime/BoxedArray.scala index 630a6874d8..61bf769c2f 100644 --- a/src/library/scala/runtime/BoxedArray.scala +++ b/src/library/scala/runtime/BoxedArray.scala @@ -11,9 +11,9 @@ package scala.runtime - import Predef._ -import collection.mutable.ArrayBuffer +import collection.mutable.{Vector, ArrayBuffer} +import collection.generic._ /** * <p>A class representing <code>Array[T]</code></p> @@ -21,7 +21,8 @@ import collection.mutable.ArrayBuffer * @author Martin Odersky, Stephane Micheloud * @version 1.0 */ -abstract class BoxedArray[A] extends Array.Array0[A] { +abstract class BoxedArray[A] extends Vector[A] with VectorTemplate[A, BoxedArray[A]] with Boxed { + /** The length of the array */ def length: Int @@ -31,24 +32,21 @@ abstract class BoxedArray[A] extends Array.Array0[A] { /** Update element at given index */ def update(index: Int, elem: A): Unit + /** Creates new builder for this collection ==> move to subclasses + * + * */ + override protected[this] def newBuilder = traversibleBuilder[A] + + override def traversibleBuilder[B]: Builder[B, BoxedArray[B], Any] = new ArrayBuffer[B].mapResult { + _.toArray.asInstanceOf[BoxedArray[B]] + } + /** Convert to Java array. * @param elemTag Either one of the tags ".N" where N is the name of a primitive type * (@see ScalaRunTime), or a full class name. */ - //todo: remove - def unbox(elemTag: String): AnyRef - def unbox(elemClass: Class[_]): AnyRef - override def isDefinedAt(x: Int): Boolean = 0 <= x && x < length - - @serializable protected class AnyIterator extends Iterator[A] { - var index = 0 - def hasNext: Boolean = index < length - def next(): A = { val i = index; index = i + 1; apply(i) } - } - override def elements = new AnyIterator - /** The underlying array value */ def value: AnyRef @@ -59,7 +57,14 @@ abstract class BoxedArray[A] extends Array.Array0[A] { def copyTo(from: Int, dest: AnyRef, to: Int, len: Int): Unit = { Array.copy(value, from, dest, to, len) } +/* + override def equals(other: Any) = + (value eq other) || + other.isInstanceOf[BoxedArray[_]] && (value == other.asInstanceOf[BoxedArray[_]].value) + + override def hashCode(): Int = value.hashCode() +*/ /** Fills the given array <code>xs</code> with the elements of * this sequence starting at position <code>start</code>. * @@ -67,62 +72,8 @@ abstract class BoxedArray[A] extends Array.Array0[A] { * @param start starting index. * @pre the array must be large enough to hold all elements. */ - override def copyToArray[B](xs: Array[B], start: Int): Unit = - copyTo(0, xs, start, length) - - // todo: add a copyToBuffer - - // todo: eliminate - def subArray(from: Int, end: Int): AnyRef - - final override def map[b](f: A => b): Array[b] = { - val len = length - val result = new Array[b](len) - var i = 0 - while (i < len) { - result(i) = f(apply(i)) - i += 1 - } - result - } - - final override def flatMap[b](f: A => Iterable[b]): Array[b] = { - val buf = new ArrayBuffer[b] - val len = length - var i = 0 - while (i < len) { - buf ++= f(apply(i)) - i += 1 - } - buf.toArray - } - - final override def ++[b >: A](that: Iterable[b]): Array[b] = super.++(that).toArray - - final def zip[b](that: Array[b]): Array[(A,b)] = { - val len = this.length min that.length - val result = new Array[(A,b)](len) - var i = 0 - while (i < len) { - result(i) = (this(i), that(i)) - i += 1 - } - result - } - - final def zipWithIndex: Array[(A,Int)] = { - val len = length - val result = new Array[(A,Int)](len) - var i = 0 - while (i < len) { - result(i) = (this(i), i) - i += 1 - } - result - } - - /** Returns an array that contains all indices of this array */ - def indices: Array[Int] = Array.range(0, length) + override def copyToArray[B](xs: Array[B], start: Int, len: Int): Unit = + copyTo(0, xs, start, len) final def deepToString() = deepMkString(stringPrefix + "(", ", ", ")") @@ -173,15 +124,21 @@ abstract class BoxedArray[A] extends Array.Array0[A] { false } } + override final def stringPrefix: String = "Array" - protected def newArray(length : Int, elements : Iterator[A]) : BoxedArray[A] - override def projection : scala.Array.Projection[A] = new scala.Array.Projection[A] { - def update(idx : Int, what : A) : Unit = BoxedArray.this.update(idx, what) - def length = BoxedArray.this.length - def apply(idx : Int) = BoxedArray.this.apply(idx) - override def stringPrefix = "ArrayP" - protected def newArray[B >: A](length : Int, elements : Iterator[A]) = - BoxedArray.this.newArray(length, elements).asInstanceOf[Array[B]] + protected def countAndMemo(p: A => Boolean): (Int, Array[Boolean]) = { + val len = length + val memo = new Array[Boolean](len) + var count = 0 + var i = 0 + while (i < len) { + if (p(this(i))) { memo(i) = true; count += 1 } + i += 1 + } + (count, memo) } + + /** @deprecated use slice instead */ + @deprecated def subArray(from: Int, end: Int): BoxedArray[A] = slice(from, end) } diff --git a/src/library/scala/runtime/BoxedBooleanArray.scala b/src/library/scala/runtime/BoxedBooleanArray.scala index bad611d3bd..6253e12ada 100644 --- a/src/library/scala/runtime/BoxedBooleanArray.scala +++ b/src/library/scala/runtime/BoxedBooleanArray.scala @@ -11,9 +11,6 @@ package scala.runtime - -import Predef._ - @serializable final class BoxedBooleanArray(val value: Array[Boolean]) extends BoxedArray[Boolean] { @@ -24,42 +21,5 @@ final class BoxedBooleanArray(val value: Array[Boolean]) extends BoxedArray[Bool def update(index: Int, elem: Boolean) { value(index) = elem } - - def unbox(elemTag: String): AnyRef = value def unbox(elemClass: Class[_]): AnyRef = value - - override def equals(other: Any) = - value == other || - other.isInstanceOf[BoxedBooleanArray] && value == other.asInstanceOf[BoxedBooleanArray].value - - override def hashCode(): Int = value.hashCode() - - def subArray(start: Int, end: Int): Array[Boolean] = { - val result = new Array[Boolean](end - start) - Array.copy(value, start, result, 0, end - start) - result - } - - final override def filter(p: Boolean => Boolean): BoxedArray[Boolean] = { - val include = new Array[Boolean](value.length) - var len = 0 - var i = 0 - while (i < value.length) { - if (p(value(i))) { include(i) = true; len += 1 } - i += 1 - } - val result = new Array[Boolean](len) - len = 0 - i = 0 - while (len < result.length) { - if (include(i)) { result(len) = value(i); len += 1 } - i += 1 - } - new BoxedBooleanArray(result) - } - override protected def newArray(length : Int, elements : Iterator[Boolean]) = { - val result = new Array[Boolean](length) - elements.map(_.asInstanceOf[Boolean]).copyToArray(result, 0) - new BoxedBooleanArray(result) - } } diff --git a/src/library/scala/runtime/BoxedByteArray.scala b/src/library/scala/runtime/BoxedByteArray.scala index 0c63acada8..ce3ad42c9e 100644 --- a/src/library/scala/runtime/BoxedByteArray.scala +++ b/src/library/scala/runtime/BoxedByteArray.scala @@ -11,9 +11,6 @@ package scala.runtime - -import Predef._ - @serializable final class BoxedByteArray(val value: Array[Byte]) extends BoxedArray[Byte] { @@ -24,44 +21,5 @@ final class BoxedByteArray(val value: Array[Byte]) extends BoxedArray[Byte] { def update(index: Int, elem: Byte) { value(index) = elem } - - def unbox(elemTag: String): AnyRef = value def unbox(elemClass: Class[_]): AnyRef = value - - override def equals(other: Any) = - value == other || - other.isInstanceOf[BoxedByteArray] && value == other.asInstanceOf[BoxedByteArray].value - - override def hashCode(): Int = value.hashCode() - - def subArray(start: Int, end: Int): Array[Byte] = { - val result = new Array[Byte](end - start) - Array.copy(value, start, result, 0, end - start) - result - } - - final override def filter(p: Byte => Boolean): BoxedArray[Byte] = { - val include = new Array[Boolean](value.length) - var len = 0 - var i = 0 - while (i < value.length) { - if (p(value(i))) { include(i) = true; len += 1 } - i += 1 - } - val result = new Array[Byte](len) - len = 0 - i = 0 - while (len < result.length) { - if (include(i)) { result(len) = value(i); len += 1 } - i += 1 - } - new BoxedByteArray(result) - } - override protected def newArray(length : Int, elements : Iterator[Byte]) = { - val result = new Array[Byte](length) - elements.map(_.asInstanceOf[Byte]).copyToArray(result, 0) - new BoxedByteArray(result) - } - - } diff --git a/src/library/scala/runtime/BoxedCharArray.scala b/src/library/scala/runtime/BoxedCharArray.scala index 54a90fbee3..519c0fda79 100644 --- a/src/library/scala/runtime/BoxedCharArray.scala +++ b/src/library/scala/runtime/BoxedCharArray.scala @@ -11,9 +11,6 @@ package scala.runtime - -import Predef._ - @serializable final class BoxedCharArray(val value: Array[Char]) extends BoxedArray[Char] { @@ -24,44 +21,5 @@ final class BoxedCharArray(val value: Array[Char]) extends BoxedArray[Char] { def update(index: Int, elem: Char) { value(index) = elem } - - def unbox(elemTag: String): AnyRef = value def unbox(elemClass: Class[_]): AnyRef = value - - override def equals(other: Any) = - value == other || - other.isInstanceOf[BoxedCharArray] && value == other.asInstanceOf[BoxedCharArray].value - - override def hashCode(): Int = value.hashCode() - - def subArray(start: Int, end: Int): Array[Char] = { - val result = new Array[Char](end - start) - Array.copy(value, start, result, 0, end - start) - result - } - - final override def filter(p: Char => Boolean): BoxedArray[Char] = { - val include = new Array[Boolean](value.length) - var len = 0 - var i = 0 - while (i < value.length) { - if (p(value(i))) { include(i) = true; len += 1 } - i += 1 - } - val result = new Array[Char](len) - len = 0 - i = 0 - while (len < result.length) { - if (include(i)) { result(len) = value(i); len += 1 } - i += 1 - } - new BoxedCharArray(result) - } - override protected def newArray(length : Int, elements : Iterator[Char]) = { - val result = new Array[Char](length) - elements.map(_.asInstanceOf[Char]).copyToArray(result, 0) - new BoxedCharArray(result) - } - - } diff --git a/src/library/scala/runtime/BoxedDoubleArray.scala b/src/library/scala/runtime/BoxedDoubleArray.scala index fdaec061e9..ff6c205f31 100644 --- a/src/library/scala/runtime/BoxedDoubleArray.scala +++ b/src/library/scala/runtime/BoxedDoubleArray.scala @@ -11,9 +11,6 @@ package scala.runtime - -import Predef._ - @serializable final class BoxedDoubleArray(val value: Array[Double]) extends BoxedArray[Double] { @@ -24,44 +21,5 @@ final class BoxedDoubleArray(val value: Array[Double]) extends BoxedArray[Double def update(index: Int, elem: Double) { value(index) = elem } - - def unbox(elemTag: String): AnyRef = value def unbox(elemClass: Class[_]): AnyRef = value - - override def equals(other: Any) = - value == other || - other.isInstanceOf[BoxedDoubleArray] && value == other.asInstanceOf[BoxedDoubleArray].value - - override def hashCode(): Int = value.hashCode() - - def subArray(start: Int, end: Int): Array[Double] = { - val result = new Array[Double](end - start) - Array.copy(value, start, result, 0, end - start) - result - } - - final override def filter(p: Double => Boolean): BoxedArray[Double] = { - val include = new Array[Boolean](value.length) - var len = 0 - var i = 0 - while (i < value.length) { - if (p(value(i))) { include(i) = true; len += 1 } - i += 1 - } - val result = new Array[Double](len) - len = 0 - i = 0 - while (len < result.length) { - if (include(i)) { result(len) = value(i); len += 1 } - i += 1 - } - new BoxedDoubleArray(result) - } - override protected def newArray(length : Int, elements : Iterator[Double]) = { - val result = new Array[Double](length) - elements.map(_.asInstanceOf[Double]).copyToArray(result, 0) - new BoxedDoubleArray(result) - } - - } diff --git a/src/library/scala/runtime/BoxedFloatArray.scala b/src/library/scala/runtime/BoxedFloatArray.scala index 05b19dd2e9..0d6ec12795 100644 --- a/src/library/scala/runtime/BoxedFloatArray.scala +++ b/src/library/scala/runtime/BoxedFloatArray.scala @@ -11,9 +11,6 @@ package scala.runtime - -import Predef._ - @serializable final class BoxedFloatArray(val value: Array[Float]) extends BoxedArray[Float] { @@ -24,44 +21,5 @@ final class BoxedFloatArray(val value: Array[Float]) extends BoxedArray[Float] { def update(index: Int, elem: Float) { value(index) = elem } - - def unbox(elemTag: String): AnyRef = value def unbox(elemClass: Class[_]): AnyRef = value - - override def equals(other: Any) = - value == other || - other.isInstanceOf[BoxedFloatArray] && value == other.asInstanceOf[BoxedFloatArray].value - - override def hashCode(): Int = value.hashCode() - - def subArray(start: Int, end: Int): Array[Float] = { - val result = new Array[Float](end - start) - Array.copy(value, start, result, 0, end - start) - result - } - - final override def filter(p: Float => Boolean): BoxedArray[Float] = { - val include = new Array[Boolean](value.length) - var len = 0 - var i = 0 - while (i < value.length) { - if (p(value(i))) { include(i) = true; len += 1 } - i += 1 - } - val result = new Array[Float](len) - len = 0 - i = 0 - while (len < result.length) { - if (include(i)) { result(len) = value(i); len += 1 } - i += 1 - } - new BoxedFloatArray(result) - } - override protected def newArray(length : Int, elements : Iterator[Float]) = { - val result = new Array[Float](length) - elements.map(_.asInstanceOf[Float]).copyToArray(result, 0) - new BoxedFloatArray(result) - } - - } diff --git a/src/library/scala/runtime/BoxedIntArray.scala b/src/library/scala/runtime/BoxedIntArray.scala index 5c062294c3..2b10dd98b1 100644 --- a/src/library/scala/runtime/BoxedIntArray.scala +++ b/src/library/scala/runtime/BoxedIntArray.scala @@ -11,9 +11,6 @@ package scala.runtime - -import Predef._ - @serializable final class BoxedIntArray(val value: Array[Int]) extends BoxedArray[Int] { @@ -24,44 +21,5 @@ final class BoxedIntArray(val value: Array[Int]) extends BoxedArray[Int] { def update(index: Int, elem: Int) { value(index) = elem } - - def unbox(elemTag: String): AnyRef = value def unbox(elemClass: Class[_]): AnyRef = value - - override def equals(other: Any) = - value == other || - other.isInstanceOf[BoxedIntArray] && value == other.asInstanceOf[BoxedIntArray].value - - override def hashCode(): Int = value.hashCode() - - def subArray(start: Int, end: Int): Array[Int] = { - val result = new Array[Int](end - start) - Array.copy(value, start, result, 0, end - start) - result - } - - final override def filter(p: Int => Boolean): BoxedArray[Int] = { - val include = new Array[Boolean](value.length) - var len = 0 - var i = 0 - while (i < value.length) { - if (p(value(i))) { include(i) = true; len += 1 } - i += 1 - } - val result = new Array[Int](len) - len = 0 - i = 0 - while (len < result.length) { - if (include(i)) { result(len) = value(i); len += 1 } - i += 1 - } - new BoxedIntArray(result) - } - override protected def newArray(length : Int, elements : Iterator[Int]) = { - val result = new Array[Int](length) - elements.map(_.asInstanceOf[Int]).copyToArray(result, 0) - new BoxedIntArray(result) - } - - } diff --git a/src/library/scala/runtime/BoxedLongArray.scala b/src/library/scala/runtime/BoxedLongArray.scala index a94e1e9f04..57bcf19cd2 100644 --- a/src/library/scala/runtime/BoxedLongArray.scala +++ b/src/library/scala/runtime/BoxedLongArray.scala @@ -11,9 +11,6 @@ package scala.runtime - -import Predef._ - @serializable final class BoxedLongArray(val value: Array[Long]) extends BoxedArray[Long] { @@ -24,44 +21,5 @@ final class BoxedLongArray(val value: Array[Long]) extends BoxedArray[Long] { def update(index: Int, elem: Long) { value(index) = elem } - - def unbox(elemTag: String): AnyRef = value def unbox(elemClass: Class[_]): AnyRef = value - - override def equals(other: Any) = - value == other || - other.isInstanceOf[BoxedLongArray] && value == other.asInstanceOf[BoxedLongArray].value - - override def hashCode(): Int = value.hashCode() - - def subArray(start: Int, end: Int): Array[Long] = { - val result = new Array[Long](end - start) - Array.copy(value, start, result, 0, end - start) - result - } - - final override def filter(p: Long => Boolean): BoxedArray[Long] = { - val include = new Array[Boolean](value.length) - var len = 0 - var i = 0 - while (i < value.length) { - if (p(value(i))) { include(i) = true; len += 1 } - i += 1 - } - val result = new Array[Long](len) - len = 0 - i = 0 - while (len < result.length) { - if (include(i)) { result(len) = value(i); len += 1 } - i += 1 - } - new BoxedLongArray(result) - } - override protected def newArray(length : Int, elements : Iterator[Long]) = { - val result = new Array[Long](length) - elements.map(_.asInstanceOf[Long]).copyToArray(result, 0) - new BoxedLongArray(result) - } - - } diff --git a/src/library/scala/runtime/BoxedObjectArray.scala b/src/library/scala/runtime/BoxedObjectArray.scala index f1f845d37f..c46e54fd81 100644 --- a/src/library/scala/runtime/BoxedObjectArray.scala +++ b/src/library/scala/runtime/BoxedObjectArray.scala @@ -29,22 +29,18 @@ final class BoxedObjectArray[A <: AnyRef](val value: Array[AnyRef]) extends Boxe def unbox(elemTag: String): AnyRef = value def unbox(elemClass: Class[_]): AnyRef = value +/* override def equals(other: Any): Boolean = (value eq other.asInstanceOf[AnyRef]) || other.isInstanceOf[BoxedObjectArray[_]] && (value eq other.asInstanceOf[BoxedObjectArray[_]].value) override def hashCode(): Int = (value.asInstanceOf[AnyRef]).hashCode() +*/ private def create(length: Int): Array[AnyRef] = { createArray(value.getClass().getComponentType(), length).asInstanceOf[Array[AnyRef]] } - override def subArray(start: Int, end: Int): Array[AnyRef] = { - val result = create(end - start) - Array.copy(value, start, result, 0, end - start) - result - } - final override def filter(p: A => Boolean): BoxedArray[A] = { val include = new Array[Boolean](value.length) var len = 0 @@ -62,11 +58,5 @@ final class BoxedObjectArray[A <: AnyRef](val value: Array[AnyRef]) extends Boxe } new BoxedObjectArray[A](result) } - - override protected def newArray(length: Int, elements: Iterator[A]) = { - val result = create(length) - elements.map(_.asInstanceOf[A]).copyToArray(result, 0) - new BoxedObjectArray[A](result) - } } diff --git a/src/library/scala/runtime/BoxedShortArray.scala b/src/library/scala/runtime/BoxedShortArray.scala index 30a879d26d..b99cc80610 100644 --- a/src/library/scala/runtime/BoxedShortArray.scala +++ b/src/library/scala/runtime/BoxedShortArray.scala @@ -11,9 +11,6 @@ package scala.runtime - -import Predef._ - @serializable final class BoxedShortArray(val value: Array[Short]) extends BoxedArray[Short] { @@ -24,44 +21,5 @@ final class BoxedShortArray(val value: Array[Short]) extends BoxedArray[Short] { def update(index: Int, elem: Short) { value(index) = elem } - - def unbox(elemTag: String): AnyRef = value def unbox(elemClass: Class[_]): AnyRef = value - - override def equals(other: Any) = - value == other || - other.isInstanceOf[BoxedShortArray] && value == other.asInstanceOf[BoxedShortArray].value - - override def hashCode(): Int = value.hashCode() - - def subArray(start: Int, end: Int): Array[Short] = { - val result = new Array[Short](end - start) - Array.copy(value, start, result, 0, end - start) - result - } - - final override def filter(p: Short => Boolean): BoxedArray[Short] = { - val include = new Array[Boolean](value.length) - var len = 0 - var i = 0 - while (i < value.length) { - if (p(value(i))) { include(i) = true; len += 1 } - i += 1 - } - val result = new Array[Short](len) - len = 0 - i = 0 - while (len < result.length) { - if (include(i)) { result(len) = value(i); len += 1 } - i += 1 - } - new BoxedShortArray(result) - } - override protected def newArray(length : Int, elements : Iterator[Short]) = { - val result = new Array[Short](length) - elements.map(_.asInstanceOf[Short]).copyToArray(result, 0) - new BoxedShortArray(result) - } - - } diff --git a/src/library/scala/runtime/RichChar.scala b/src/library/scala/runtime/RichChar.scala index cd4d979c5e..943e5516f5 100644 --- a/src/library/scala/runtime/RichChar.scala +++ b/src/library/scala/runtime/RichChar.scala @@ -11,9 +11,10 @@ package scala.runtime - import java.lang.Character -import Predef.NoSuchElementException +import collection.Vector +import collection.generic.VectorView +import Predef.{require, NoSuchElementException} /** <p> * For example, in the following code @@ -52,24 +53,22 @@ final class RichChar(x: Char) extends Proxy with Ordered[Char] { def toLowerCase: Char = Character.toLowerCase(x) def toUpperCase: Char = Character.toUpperCase(x) - /** Create a <code>RandomAccessSeq.Projection[Char]</code> over the characters from 'x' to 'y' - 1 + /** Create a <code>[Char]</code> over the characters from 'x' to 'y' - 1 */ - def until(limit: Char): RandomAccessSeq.Projection[Char] = - if (limit <= x) RandomAccessSeq.empty.projection + def until(limit: Char): VectorView[Char, Vector[Char]] = + if (limit <= x) Vector.empty.view else - new RandomAccessSeq.Projection[Char] { + new VectorView[Char, Vector[Char]] { + protected def underlying = Vector.empty[Char] def length = limit - x def apply(i: Int): Char = { - Predef.require(i >= 0 && i < length) + require(i >= 0 && i < length) (x + i).toChar } - override def stringPrefix = "RandomAccessSeq.Projection" } - //def until(y: Char): Iterator[Char] = to(y) - /** Create a <code>RandomAccessSeq.Projection[Char]</code> over the characters from 'x' to 'y' */ - def to(y: Char): RandomAccessSeq.Projection[Char] = until((y + 1).toChar) + def to(y: Char): VectorView[Char, Vector[Char]] = until((y + 1).toChar) } diff --git a/src/library/scala/runtime/RichInt.scala b/src/library/scala/runtime/RichInt.scala index 8da0a4076f..c62d8fcd06 100644 --- a/src/library/scala/runtime/RichInt.scala +++ b/src/library/scala/runtime/RichInt.scala @@ -27,7 +27,7 @@ final class RichInt(start: Int) extends Proxy with Ordered[Int] { def until(end: Int, step: Int): Range = new Range(start, end, step) /** like <code>until</code>, but includes the last index */ - def to(end: Int) = new Range.Inclusive(start, end, 1) + def to(end: Int) = Range.inclusive(start, end, 1) def min(that: Int): Int = if (start < that) start else that def max(that: Int): Int = if (start > that) start else that diff --git a/src/library/scala/runtime/RichString.scala b/src/library/scala/runtime/RichString.scala index 0fb6ee403e..44bf12a4dd 100644 --- a/src/library/scala/runtime/RichString.scala +++ b/src/library/scala/runtime/RichString.scala @@ -11,68 +11,41 @@ package scala.runtime -import Predef._ import scala.util.matching.Regex +import collection.generic._ +//import collection.mutable.StringBuilder +import collection.immutable.Vector -final class RichString(val self: String) extends Proxy with RandomAccessSeq[Char] with Ordered[String] { - import RichString._ - override def apply(n: Int) = self charAt n - override def length = self.length - override def toString = self - override def mkString = self - - override def slice(from: Int, until: Int): RichString = { - val len = self.length - new RichString( - if (from >= until || from >= len) - "" - else { - val from0 = if (from < 0) 0 else from - val until0 = if (until > len) len else until - self.substring(from0, until0) - } - ) - } +object RichString { - //override def ++ [B >: A](that: Iterable[B]): Seq[B] = { - override def ++[B >: Char](that: Iterable[B]): RandomAccessSeq[B] = that match { - case that: RichString => new RichString(self + that.self) - case that => super.++(that) - } +// def newBuilder: Builder[Char, String, Any] = new StringBuilder() + def newBuilder: Builder[Char, RichString, Any] = new StringBuilder() mapResult (new RichString(_)) + implicit def builderFactory: BuilderFactory[Char, RichString, RichString] = new BuilderFactory[Char, RichString, RichString] { def apply(from: RichString) = newBuilder } + implicit def builderFactory2: BuilderFactory[Char, RichString, String] = new BuilderFactory[Char, RichString, String] { def apply(from: String) = newBuilder } - override def take(until: Int): RichString = slice(0, until) + // just statics for rich string. + private final val LF: Char = 0x0A + private final val FF: Char = 0x0C + private final val CR: Char = 0x0D + private final val SU: Char = 0x1A +} - override def drop(from: Int): RichString = slice(from, self.length) +import RichString._ - override def startsWith[B](that: Seq[B]) = that match { - case that: RichString => self startsWith that.self - case that => super.startsWith(that) - } +class RichString(val self: String) extends Proxy with Vector[Char] with VectorTemplate[Char, RichString] with PartialFunction[Int, Char] with Ordered[String] { - override def endsWith[B](that: Seq[B]) = that match { - case that: RichString => self endsWith that.self - case that => super.endsWith(that) - } + /** Creates a string builder buffer as builder for this class */ + override protected[this] def newBuilder = RichString.newBuilder - override def indexOf[B](that: Seq[B]) = that match { - case that: RichString => self indexOf that.self - case that => super.indexOf(that) - } + /** Return element at index `n` + * @throws IndexOutofBoundsException if the index is not valid + */ + def apply(n: Int): Char = self charAt n - override def containsSlice[B](that: Seq[B]) = that match { - case that: RichString => self contains that.self - case that => super.containsSlice(that) - } + def length: Int = self.length - override def reverse: RichString = { - val buf = new StringBuilder - var i = self.length - 1 - while (i >= 0) { - buf append (self charAt i) - i -= 1 - } - new RichString(buf.toString) - } + override def mkString = self + override def toString = self /** return n times the current string */ @@ -211,6 +184,15 @@ final class RichString(val self: String) extends Proxy with RandomAccessSeq[Char def toFloat: Float = java.lang.Float.parseFloat(self) def toDouble: Double = java.lang.Double.parseDouble(self) + private def parseBoolean(s: String): Boolean = + if (s != null) s.toLowerCase match { + case "true" => true + case "false" => false + case _ => throw new NumberFormatException("For input string: \""+s+"\"") + } + else + throw new NumberFormatException("For input string: \"null\"") + def toArray: Array[Char] = { val result = new Array[Char](length) self.getChars(0, length, result, 0) @@ -236,19 +218,3 @@ final class RichString(val self: String) extends Proxy with RandomAccessSeq[Char java.lang.String.format(self, args.toList.toArray[Any].asInstanceOf[Array[AnyRef]]: _*) } -object RichString { - // just statics for rich string. - private final val LF: Char = 0x0A - private final val FF: Char = 0x0C - private final val CR: Char = 0x0D - private final val SU: Char = 0x1A - - private def parseBoolean(s: String): Boolean = - if (s != null) s.toLowerCase match { - case "true" => true - case "false" => false - case _ => throw new NumberFormatException("For input string: \""+s+"\"") - } - else - throw new NumberFormatException("For input string: \"null\"") -} diff --git a/src/library/scala/runtime/RichStringBuilder.scala b/src/library/scala/runtime/RichStringBuilder.scala deleted file mode 100644 index 51a3a00369..0000000000 --- a/src/library/scala/runtime/RichStringBuilder.scala +++ /dev/null @@ -1,57 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime - - -import Predef._ -import scala.collection.mutable.{Buffer,ArrayBuffer} - -final class RichStringBuilder(val self : StringBuilder) extends RandomAccessSeq.Mutable[Char] with Proxy with Buffer[Char] { - override def length = self.length - override def apply(idx : Int) = self.charAt(idx) - override def mkString = self.toString - override def update(idx : Int, c : Char) = self.setCharAt(idx, c) - override def +=(c: Char): Unit = self append c - override def ++=(iter: Iterable[Char]): Unit = iter match { - case str : RichString => self append str.self - case str : Array[Char] => self append str - case iter => super.++=(iter) - } - override def ++(iter: Iterable[Char]): RichStringBuilder = { this ++= iter; this } - override def ++[B >: Char](that : Iterable[B]) : RandomAccessSeq[B] = { - val buf = new ArrayBuffer[B] - this copyToBuffer buf - that copyToBuffer buf - buf - } - - - override def insertAll(idx: Int, iter: Iterable[Char]): Unit = iter match { - case str : RichString => self.insert(idx, str) - case str : Array[Char] => self.insert(idx, str) - case iter => - val i = iter.elements - var jdx = idx - while (i.hasNext) { - self.insert(jdx, i.next) - jdx = jdx + 1 - } - } - override def +:(c : Char) = self.insert(0, c) - def ensureSize(size : Int) = self.ensureCapacity(size) - override def remove(idx : Int) = { - val c = self.charAt(idx) - self.deleteCharAt(idx) - c - } - override def clear = self.setLength(0) -} diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index 84f1945177..8f1acb8381 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -11,25 +11,11 @@ package scala.runtime - -import Predef._ - /* The object <code>ScalaRunTime</code> provides ... */ object ScalaRunTime { - /** Names for primitive types, used by array unboxing */ - val ByteTag = ".Byte" - val ShortTag = ".Short" - val CharTag = ".Char" - val IntTag = ".Int" - val LongTag = ".Long" - val FloatTag = ".Float" - val DoubleTag = ".Double" - val BooleanTag = ".Boolean" - def isArray(x: AnyRef): Boolean = (x != null && x.getClass.isArray) || (x != null && x.isInstanceOf[BoxedArray[_]]) - def isValueTag(tag: String) = tag.charAt(0) == '.' def isValueClass(clazz: Class[_]) = clazz.isPrimitive() def forceBoxedArray[A <: Any](xs: Seq[A]): Array[A] = { @@ -127,9 +113,6 @@ object ScalaRunTime { def Seq[a](xs: a*): Seq[a] = null // interpreted specially by new backend. - def arrayValue[A](x: BoxedArray[A], elemTag: String): AnyRef = - if (x eq null) null else x.unbox(elemTag) - def arrayValue[A](x: BoxedArray[A], elemClass: Class[_]): AnyRef = if (x eq null) null else x.unbox(elemClass) diff --git a/src/library/scala/util/automata/BaseBerrySethi.scala b/src/library/scala/util/automata/BaseBerrySethi.scala index fbe23be42a..d35e84fd83 100644 --- a/src/library/scala/util/automata/BaseBerrySethi.scala +++ b/src/library/scala/util/automata/BaseBerrySethi.scala @@ -35,11 +35,11 @@ abstract class BaseBerrySethi { protected var finalTag: Int = _ - protected var finals: immutable.TreeMap[Int, Int] = _ // final states + protected var finals: immutable.Map[Int, Int] = _ // final states // constants -------------------------- - final val emptySet:immutable.Set[Int] = new immutable.TreeSet[Int]() + final val emptySet:immutable.Set[Int] = immutable.Set[Int]() /** computes first( r ) for the word regexp r */ protected def compFirst(r: RegExp): immutable.Set[Int] = r match { diff --git a/src/library/scala/util/automata/DetWordAutom.scala b/src/library/scala/util/automata/DetWordAutom.scala index b8e18139be..0f812b2270 100644 --- a/src/library/scala/util/automata/DetWordAutom.scala +++ b/src/library/scala/util/automata/DetWordAutom.scala @@ -59,10 +59,10 @@ abstract class DetWordAutom[T <: AnyRef] { val sb = new StringBuilder("[DetWordAutom nstates=") sb.append(nstates) sb.append(" finals=") - var map = new scala.collection.immutable.ListMap[Int,Int] + var map = scala.collection.immutable.Map[Int,Int]() var j = 0; while( j < nstates ) { if (j < finals.length) - map = map.update(j, finals(j)) + map = map.add(j, finals(j)) j += 1 } sb.append(map.toString()) diff --git a/src/library/scala/util/automata/NondetWordAutom.scala b/src/library/scala/util/automata/NondetWordAutom.scala index 461570fcdd..89686c47d4 100644 --- a/src/library/scala/util/automata/NondetWordAutom.scala +++ b/src/library/scala/util/automata/NondetWordAutom.scala @@ -89,10 +89,10 @@ abstract class NondetWordAutom[T <: AnyRef] { val sb = new StringBuilder("[NondetWordAutom nstates=") sb.append(nstates) sb.append(" finals=") - var map = new scala.collection.immutable.ListMap[Int,Int] + var map = scala.collection.immutable.Map[Int,Int]() var j = 0; while (j < nstates) { if (isFinal(j)) - map = map.update(j, finals(j)); + map = map.add(j, finals(j)); j += 1 } sb.append(map.toString) diff --git a/src/library/scala/util/automata/SubsetConstruction.scala b/src/library/scala/util/automata/SubsetConstruction.scala index 16f9b91ac9..3d8cb34f29 100644 --- a/src/library/scala/util/automata/SubsetConstruction.scala +++ b/src/library/scala/util/automata/SubsetConstruction.scala @@ -15,7 +15,7 @@ package scala.util.automata class SubsetConstruction[T <: AnyRef](val nfa: NondetWordAutom[T]) { import nfa.labels import scala.collection.{immutable, mutable, Map} - import immutable.{BitSet, TreeMap, TreeSet} + import immutable.BitSet implicit def toOrdered(bs: BitSet): Ordered[BitSet] = new Ordered[BitSet] { def compare(that: BitSet): Int = { @@ -77,16 +77,16 @@ class SubsetConstruction[T <: AnyRef](val nfa: NondetWordAutom[T]) { def determinize: DetWordAutom[T] = { // for assigning numbers to bitsets - var indexMap = new TreeMap[BitSet, Int] - var invIndexMap = new TreeMap[Int, BitSet] + var indexMap = Map[BitSet, Int]() + var invIndexMap = Map[Int, BitSet]() var ix = 0 // we compute the dfa with states = bitsets - var states = new TreeSet[BitSet]() + var states = Set[BitSet]() val delta = new mutable.HashMap[BitSet, mutable.HashMap[T, BitSet]] - var deftrans = new TreeMap[BitSet, BitSet] - var finals = new TreeMap[BitSet, Int] + var deftrans = Map[BitSet, BitSet]() + var finals = Map[BitSet, Int]() val q0 = _initialBitSet states = states + q0 @@ -94,17 +94,17 @@ class SubsetConstruction[T <: AnyRef](val nfa: NondetWordAutom[T]) { val sink = _emptyBitSet states = states + sink - deftrans = deftrans.update(q0,sink); - deftrans = deftrans.update(sink,sink); + deftrans = deftrans.add(q0,sink); + deftrans = deftrans.add(sink,sink); - val rest = new mutable.Stack[BitSet](); + val rest = new mutable.ArrayStack[BitSet](); def add(Q: BitSet) { if (!states.contains(Q)) { states = states + Q rest.push(Q) if (nfa.containsFinal(Q)) - finals = finals.update(Q, selectTag(Q,nfa.finals)); + finals = finals.add(Q, selectTag(Q,nfa.finals)); } } rest.push(sink) @@ -113,24 +113,24 @@ class SubsetConstruction[T <: AnyRef](val nfa: NondetWordAutom[T]) { while (!rest.isEmpty) { // assign a number to this bitset val P = rest.pop - indexMap = indexMap.update(P,ix) - invIndexMap = invIndexMap.update(ix,P) + indexMap = indexMap.add(P,ix) + invIndexMap = invIndexMap.add(ix,P) ix += 1 // make transitiion map val Pdelta = new mutable.HashMap[T, BitSet] - delta.update(P, Pdelta) + delta.add(P, Pdelta) val it = labels.elements; while(it.hasNext) { val label = it.next val Q = nfa.next(P,label) - Pdelta.update(label, Q) + Pdelta.add(label, Q) add(Q) } // collect default transitions val Pdef = nfa.nextDefault(P) - deftrans = deftrans.update(P, Pdef) + deftrans = deftrans.add(P, Pdef) add(Pdef) }; @@ -151,10 +151,10 @@ class SubsetConstruction[T <: AnyRef](val nfa: NondetWordAutom[T]) { val label = it.next val p = indexMap(trans(label)) if (p != qDef) - ntrans.update(label, p) + ntrans.add(label, p) } - deltaR.update(q, ntrans) - defaultR.update(q, qDef) + deltaR(q) = ntrans + defaultR(q) = qDef //cleanup? leave to garbage collector? //delta.remove(Q); diff --git a/src/library/scala/util/automata/WordBerrySethi.scala b/src/library/scala/util/automata/WordBerrySethi.scala index 3157ea560b..72b065f3e1 100644 --- a/src/library/scala/util/automata/WordBerrySethi.scala +++ b/src/library/scala/util/automata/WordBerrySethi.scala @@ -33,7 +33,7 @@ abstract class WordBerrySethi extends BaseBerrySethi { protected var labels:mutable.HashSet[_labelT] = _ // don't let this fool you, only labelAt is a real, surjective mapping - protected var labelAt: immutable.TreeMap[Int, _labelT] = _ // new alphabet "gamma" + protected var labelAt: immutable.Map[Int, _labelT] = _ // new alphabet "gamma" protected var deltaq: Array[mutable.HashMap[_labelT,List[Int]]] = _ // delta @@ -80,7 +80,7 @@ abstract class WordBerrySethi extends BaseBerrySethi { case x:Letter => //val i = posMap(x) val i = x.pos - this.follow.update(i, fol1) + this.follow.add(i, fol1) emptySet + i case Eps => emptySet /*ignore*/ @@ -96,8 +96,8 @@ abstract class WordBerrySethi extends BaseBerrySethi { /** called at the leaves of the regexp */ protected def seenLabel(r: RegExp, i: Int, label: _labelT) { //Console.println("seenLabel (1)"); - //this.posMap.update(r, i) - this.labelAt = this.labelAt.update(i, label) + //this.posMap.add(r, i) + this.labelAt = this.labelAt.add(i, label) //@ifdef if( label != Wildcard ) { this.labels += label //@ifdef } @@ -121,10 +121,10 @@ abstract class WordBerrySethi extends BaseBerrySethi { protected def makeTransition(src: Int, dest: Int, label: _labelT ) { //@ifdef compiler if( label == Wildcard ) - //@ifdef compiler defaultq.update(src, dest::defaultq( src )) + //@ifdef compiler defaultq.add(src, dest::defaultq( src )) //@ifdef compiler else val q = deltaq(src) - q.update(label, dest::(q.get(label) match { + q.add(label, dest::(q.get(label) match { case Some(x) => x case _ => Nil })) @@ -132,7 +132,7 @@ abstract class WordBerrySethi extends BaseBerrySethi { protected def initialize(subexpr: Seq[RegExp]): Unit = { //this.posMap = new mutable.HashMap[RegExp,Int]() - this.labelAt = new immutable.TreeMap[Int, _labelT]() + this.labelAt = immutable.Map[Int, _labelT]() this.follow = new mutable.HashMap[Int, immutable.Set[Int]]() this.labels = new mutable.HashSet[_labelT]() @@ -149,7 +149,7 @@ abstract class WordBerrySethi extends BaseBerrySethi { } protected def initializeAutom() { - finals = immutable.TreeMap.empty[Int, Int] // final states + finals = immutable.Map.empty[Int, Int] // final states deltaq = new Array[mutable.HashMap[_labelT, List[Int]]](pos) // delta defaultq = new Array[List[Int]](pos) // default transitions @@ -171,7 +171,7 @@ abstract class WordBerrySethi extends BaseBerrySethi { while (it.hasNext) { val k = it.next if (pos == k) - finals = finals.update(j, finalTag) + finals = finals.add(j, finalTag) else makeTransition( j, k, labelAt(k)) } @@ -195,14 +195,14 @@ abstract class WordBerrySethi extends BaseBerrySethi { collectTransitions() if (x.isNullable) // initial state is final - finals = finals.update(0, finalTag) + finals = finals.add(0, finalTag) - var delta1: immutable.TreeMap[Int, Map[_labelT, List[Int]]] = - new immutable.TreeMap[Int, Map[_labelT, List[Int]]] + var delta1: immutable.Map[Int, Map[_labelT, List[Int]]] = + immutable.Map[Int, Map[_labelT, List[Int]]]() var i = 0 while (i < deltaq.length) { - delta1 = delta1.update(i, deltaq(i)) + delta1 = delta1.add(i, deltaq(i)) i += 1 } val finalsArr = new Array[Int](pos) @@ -239,7 +239,7 @@ abstract class WordBerrySethi extends BaseBerrySethi { val x = new mutable.BitSet(pos) for (q <- trans(lab)) x += q - hmap.update(lab, x.toImmutable) + hmap.add(lab, x.toImmutable) } deltaArr(k) = hmap k += 1 diff --git a/src/library/scalax/util/control/Breaks.scala b/src/library/scala/util/control/Breaks.scala index e89a03f76b..b3eaad23ae 100755 --- a/src/library/scalax/util/control/Breaks.scala +++ b/src/library/scala/util/control/Breaks.scala @@ -1,4 +1,4 @@ -package scalax.util.control +package scala.util.control object Breaks { private class BreakException extends RuntimeException diff --git a/src/library/scalax/util/control/TailRec.scala b/src/library/scala/util/control/TailRec.scala index db6cbfa2ed..db6cbfa2ed 100644..100755 --- a/src/library/scalax/util/control/TailRec.scala +++ b/src/library/scala/util/control/TailRec.scala diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala index ba770c868b..67d37083e8 100644 --- a/src/library/scala/util/matching/Regex.scala +++ b/src/library/scala/util/matching/Regex.scala @@ -194,7 +194,7 @@ object Regex { if (end(i) >= 0) source.subSequence(end(i), source.length) else null - private lazy val nameToIndex: Map[String, Int] = Map() ++ ("" :: groupNames.toList).zipWithIndex + private lazy val nameToIndex: Map[String, Int] = Map[String, Int]() ++ ("" :: groupNames.toList).zipWithIndex /** Returns the group with given name * diff --git a/src/library/scala/util/parsing/ast/Binders.scala b/src/library/scala/util/parsing/ast/Binders.scala index 3bca5ba5e4..75ce3b28d0 100644 --- a/src/library/scala/util/parsing/ast/Binders.scala +++ b/src/library/scala/util/parsing/ast/Binders.scala @@ -92,7 +92,7 @@ trait Binders extends AbstractSyntax with Mappable { */ class Scope[binderType <: NameElement] extends Iterable[binderType]{ private val substitution: Map[binderType, Element] = - new scala.collection.jcl.LinkedHashMap[binderType, Element] // a LinkedHashMap is ordered by insertion order -- important! + new scala.collection.mutable.LinkedHashMap[binderType, Element] // a LinkedHashMap is ordered by insertion order -- important! /** Returns a unique number identifying this Scope (only used for representation purposes). */ diff --git a/src/library/scala/xml/Attribute.scala b/src/library/scala/xml/Attribute.scala index 261e9d9c86..261e9d9c86 100644..100755 --- a/src/library/scala/xml/Attribute.scala +++ b/src/library/scala/xml/Attribute.scala diff --git a/src/library/scala/xml/MetaData.scala b/src/library/scala/xml/MetaData.scala index bca5fe08a1..d947e40ee3 100644 --- a/src/library/scala/xml/MetaData.scala +++ b/src/library/scala/xml/MetaData.scala @@ -81,7 +81,7 @@ object MetaData { * @author Burak Emir <bqe@google.com> */ @serializable -abstract class MetaData extends Collection[MetaData] { +abstract class MetaData extends Iterable[MetaData] { /** updates this MetaData with the MetaData given as argument. All attributes that occur in updates * are part of the resulting MetaData. If an unprefixed attribute occurs in both this instance and @@ -181,7 +181,7 @@ abstract class MetaData extends Collection[MetaData] { y } } - def size : Int = 1 + { + override def size : Int = 1 + { if (Null == next) 0 else next.size } diff --git a/src/library/scala/xml/NodeSeq.scala b/src/library/scala/xml/NodeSeq.scala index 1316c51578..c6d6625be3 100644 --- a/src/library/scala/xml/NodeSeq.scala +++ b/src/library/scala/xml/NodeSeq.scala @@ -11,6 +11,9 @@ package scala.xml +import collection.immutable +import collection.generic._ +import collection.mutable.ListBuffer /** This object ... * @@ -22,7 +25,10 @@ object NodeSeq { def fromSeq(s: Seq[Node]): NodeSeq = new NodeSeq { def theSeq = s } - implicit def view(s: Seq[Node]): NodeSeq = fromSeq(s) + type Coll = NodeSeq + implicit def builderFactory: BuilderFactory[Node, NodeSeq, Coll] = new BuilderFactory[Node, NodeSeq, Coll] { def apply(from: Coll) = newBuilder } + def newBuilder: Builder[Node, NodeSeq, Any] = new ListBuffer[Node] mapResult fromSeq + implicit def seqToNodeSeq(s: Seq[Node]): NodeSeq = fromSeq(s) } /** This class implements a wrapper around <code>Seq[Node]</code> that @@ -31,8 +37,12 @@ object NodeSeq { * @author Burak Emir * @version 1.0 */ -abstract class NodeSeq extends Seq[Node] { - import NodeSeq.view // import view magic for NodeSeq wrappers +abstract class NodeSeq extends immutable.Sequence[Node] with SequenceTemplate[Node, NodeSeq] { + import NodeSeq.seqToNodeSeq // import view magic for NodeSeq wrappers + + /** Creates a list buffer as builder for this class */ + override protected[this] def newBuilder = NodeSeq.newBuilder + def theSeq: Seq[Node] def length = theSeq.length override def elements = theSeq.elements diff --git a/src/library/scala/xml/parsing/XhtmlEntities.scala b/src/library/scala/xml/parsing/XhtmlEntities.scala index cdfe274ed4..0b12a47162 100644 --- a/src/library/scala/xml/parsing/XhtmlEntities.scala +++ b/src/library/scala/xml/parsing/XhtmlEntities.scala @@ -34,7 +34,7 @@ object XhtmlEntities { ("xi",958), ("omicron",959), ("pi",960), ("rho",961), ("sigmaf",962), ("sigma",963), ("tau",964), ("upsilon",965), ("phi",966), ("chi",967), ("psi",968), ("omega",969), ("thetasym",977), ("upsih",978), ("piv",982)) - val entMap: Map[String, Char] = Map.empty ++ entList.map { case (name, value) => (name, value.toChar)} + val entMap: Map[String, Char] = Map.empty[String, Char] ++ entList.map { case (name, value) => (name, value.toChar)} val entities = entList. map { case (name, value) => (name, new ParsedEntityDecl(name, new IntDef(value.toChar.toString)))} diff --git a/src/library/scalax/Tuple2.scala b/src/library/scalax/Tuple2.scala deleted file mode 100755 index 4adb9e471b..0000000000 --- a/src/library/scalax/Tuple2.scala +++ /dev/null @@ -1,97 +0,0 @@ - -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Tuple2.scala 14794 2008-04-23 08:15:17Z washburn $ - -// generated by genprod on Wed Apr 23 10:06:16 CEST 2008 (with extra methods) - -package scalax - -import annotation.unchecked.uncheckedVariance - -object Tuple2 { - - import collection._ - import collection.generic._ - - class IterableOps[CC[+B] <: Iterable[B] with IterableTemplate[CC, B @uncheckedVariance], A1, A2](tuple: (CC[A1], Iterable[A2])) { - def zip: CC[(A1, A2)] = { - val elems1 = tuple._1.elements - val elems2 = tuple._2.elements - val b = tuple._1.newBuilder[(A1, A2)] - while (elems1.hasNext && elems2.hasNext) - b += ((elems1.next, elems2.next)) - b.result - } - def map[B](f: (A1, A2) => B): CC[B] = { - val elems1 = tuple._1.elements - val elems2 = tuple._2.elements - val b = tuple._1.newBuilder[B] - while (elems1.hasNext && elems2.hasNext) - b += f(elems1.next, elems2.next) - b.result - } - def flatMap[B](f: (A1, A2) => CC[B]): CC[B] = { - val elems1 = tuple._1.elements - val elems2 = tuple._2.elements - val b = tuple._1.newBuilder[B] - while (elems1.hasNext && elems2.hasNext) - b ++= f(elems1.next, elems2.next) - b.result - } - def foreach(f: (A1, A2) => Unit) { - val elems1 = tuple._1.elements - val elems2 = tuple._2.elements - while (elems1.hasNext && elems2.hasNext) - f(elems1.next, elems2.next) - } - def forall(p: (A1, A2) => Boolean): Boolean = { - val elems1 = tuple._1.elements - val elems2 = tuple._2.elements - while (elems1.hasNext && elems2.hasNext) - if (!p(elems1.next, elems2.next)) return false - true - } - def exists(p: (A1, A2) => Boolean): Boolean = { - val elems1 = tuple._1.elements - val elems2 = tuple._2.elements - while (elems1.hasNext && elems2.hasNext) - if (p(elems1.next, elems2.next)) return true - false - } - } - implicit def tupleOfIterableWrapper[CC[+B] <: Iterable[B] with IterableTemplate[CC, B], A1, A2](tuple: (CC[A1], Iterable[A2])) = - new IterableOps[CC, A1, A2](tuple) - - -/* A more general version which will probably not work. - implicit def tupleOfIterableWrapper[CC[+B] <: Iterable[B] with IterableTemplate[CC, B], A1, A2, B1 <: CC[A1]](tuple: B1, Iterable[A2]) = - new IterableOps[CC, A1, A2](tuple) -*/ - - // Adriaan: If you drop the type parameters it will infer the wrong types. - tupleOfIterableWrapper[collection.immutable.List, Int, Int]((collection.immutable.Nil, collection.immutable.Nil)) forall (_ + _ < 10) -} - -/** Tuple2 is the canonical representation of a @see Product2 - * - */ -case class Tuple2[+T1, +T2](_1:T1, _2:T2) - extends Product2[T1, T2] { - - override def toString() = { - val sb = new StringBuilder - sb.append('(').append(_1).append(',').append(_2).append(')') - sb.toString - } - - /** Swap the elements of the tuple */ - def swap: Tuple2[T2,T1] = Tuple2(_2, _1) - -} diff --git a/src/library/scalax/collection/Iterable.scala b/src/library/scalax/collection/Iterable.scala deleted file mode 100755 index 3dc181707c..0000000000 --- a/src/library/scalax/collection/Iterable.scala +++ /dev/null @@ -1,160 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - - -package scalax.collection - -import generic._ -import collection.immutable.{List, Nil, ::} -import annotation.unchecked.uncheckedVariance - -/** Collection classes mixing in this class provide a method - * <code>elements</code> which returns an iterator over all the - * elements contained in the collection. - * - * @note If a collection has a known <code>size</code>, it should also sub-type <code>SizedIterable</code>. - * - * @author Matthias Zenger - * @autor Martin Odersky - * @owner Martin Odersky - * @version 2.8 - */ -trait Iterable[+A] extends IterableTemplate[Iterable, A @uncheckedVariance] { self => - - /** Creates a view of this iterable @see Iterable.View - def view: View[Iterable, A] = new View[Iterable, A] { // !!! Martin: We should maybe infer the type parameters here? - val origin: self.type = self - val elements: Iterator[A] = self.elements - } - */ -} - -/** Various utilities for instances of <a href="Iterable.html">Iterable</a>. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.8 - */ -object Iterable extends IterableFactory[Iterable] with EmptyIterableFactory[Iterable] { - - /** The empty iterable */ - val empty: Iterable[Nothing] = Nil - - class ComparableIterableOps[A](seq: Iterable[A], cmp: Ordering[A]) { - def min: A = { - require(!seq.isEmpty, "min(<empty>)") - var acc = seq.elements.next - for (x <- seq) - if (cmp.lt(x, acc)) acc = x - acc - } - def max: A = { - require(!seq.isEmpty, "max(<empty>)") - var acc = seq.elements.next - for (x <- seq) - if (cmp.gt(x, acc)) acc = x - acc - } - } - - class NumericIterableOps[A](seq: Iterable[A], num: Numeric[A]) { - def sum: A = { - var acc = num.zero - for (x <- seq) acc = num.plus(acc, x) - acc - } - def product: A = { - var acc = num.one - for (x <- seq) acc = num.times(acc, x) - acc - } - } - - class IterableIterableOps[C[+B] <: Iterable[B] with IterableTemplate[C, B @uncheckedVariance], A](self: C[C[A]]) { - def flatten: C[A] = { - val b: generic.Builder[C, A] = self.newBuilder[A] - for (xs <- self) - b ++= xs - b.result - } - - def transpose: C[C[A]] = { - val bs: scala.Array[generic.Builder[C, A]] = self.head.map(_ => self.newBuilder[A]).toArray - for (xs <- self) { - var i = 0 - for (x <- xs) { - bs(i) += x - i += 1 - } - } - val bb = self.newBuilder[C[A]] - for (b <- bs) bb += b.result - bb.result - } - } - - - class PairIterableOps[C[+B] <: Iterable[B], A1, A2](self: C[(A1, A2)]) { - def unzip: (C[A1], C[A2]) = { - val as = self.newBuilder[A1].asInstanceOf[Builder[C, A1]] - val bs = self.newBuilder[A2].asInstanceOf[Builder[C, A2]] - for ((a, b) <- self) { - as += a - bs += b - } - (as.result, bs.result) - } - } - - implicit def comparableIterableWrapper[A](seq: Iterable[A])(implicit cmp: Ordering[A]) = - new ComparableIterableOps(seq, cmp) - implicit def numericIterableWrapper[A](seq: Iterable[A])(implicit num: Numeric[A]) = - new NumericIterableOps(seq, num) - implicit def iterableIterableWrapper[C[+B] <: Iterable[B] with IterableTemplate[C, B], A](seq: C[C[A]]) = - new IterableIterableOps[C, A](seq) - implicit def pairIterableWrapper[C[+B] <: Iterable[B], A1, A2](seq: C[(A1, A2)]) = - new PairIterableOps[C, A1, A2](seq) - - type View[A] = IterableView[UC, A] forSome { type UC[B] <: Iterable[B] } - - /** @deprecated use View instead - */ - @deprecated type Projection[A] = View[A] - - /** The minimum element of a non-empty sequence of ordered elements - * @deprecated use seq.min instead - */ - @deprecated def min[A <% Ordered[A]](seq: Iterable[A]): A = { - val xs = seq.elements - if (!xs.hasNext) throw new IllegalArgumentException("min(<empty>)") - var min = xs.next - while (xs.hasNext) { - val x = xs.next - if (x < min) min = x - } - min - } - - /** The maximum element of a non-empty sequence of ordered elements - * @deprecated use seq.max iConstead - */ - @deprecated def max[A <% Ordered[A]](seq: Iterable[A]): A = { - val xs = seq.elements - if (!xs.hasNext) throw new IllegalArgumentException("max(<empty>)") - var max = xs.next - while (xs.hasNext) { - val x = xs.next - if (max < x) max = x - } - max - } - -} - diff --git a/src/library/scalax/collection/OrderedIterable.scala b/src/library/scalax/collection/OrderedIterable.scala deleted file mode 100755 index 9a0b77e575..0000000000 --- a/src/library/scalax/collection/OrderedIterable.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - - -package scalax.collection - -import generic._ -import immutable.Nil -import annotation.unchecked.uncheckedVariance - -/** An ordered collection is a collection with a fixed sequence of elements - * which is the same in every run. - * - * for any two ordered collections c1 and c2. - * Ordered collections support - * - operations that form subsequences: take, takeWhile, drop, dropWhile, - * - zip, unzip - * - * @author Martin Odersky - * @version 2.8 - */ -trait OrderedIterable[+A] extends Iterable[A] with OrderedIterableTemplate[OrderedIterable, A @uncheckedVariance] - -/** Various utilities for instances of <a href="Iterable.html">Iterable</a>. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.8 - */ -object OrderedIterable extends IterableFactory[OrderedIterable] with EmptyIterableFactory[OrderedIterable] { - - val empty: OrderedIterable[Nothing] = Nil - -} diff --git a/src/library/scalax/collection/Sequence.scala b/src/library/scalax/collection/Sequence.scala deleted file mode 100755 index 48081c99e8..0000000000 --- a/src/library/scalax/collection/Sequence.scala +++ /dev/null @@ -1,47 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ - - -package scalax.collection - -import generic._ -import immutable.Nil -import annotation.unchecked.uncheckedVariance - -/** Class <code>Sequence[A]</code> represents finite sequences of elements - * of type <code>A</code>. - * - * @author Martin Odersky - * @author Matthias Zenger - * @version 1.0, 16/07/2003 - */ -trait Sequence[+A] extends OrderedIterable[A] with SizedIterable[A] with SequenceTemplate[Sequence, A @uncheckedVariance] - -object Sequence extends SequenceFactory[Sequence] with EmptyIterableFactory[Sequence] { - - /** The empty sequence */ - val empty : Sequence[Nothing] = immutable.Nil - - type View[+UC[B] <: Sequence[B], A] = SequenceView[UC, A] - - /** @deprecated use View instead - */ - @deprecated type Projection[A] = View[C, A] forSome { type C[+B] <: Sequence[B] } - - /** @deprecated use Sequence(value) instead */ - @deprecated def singleton[A](value: A) = Sequence(value) - - /** Builds a singleton sequence. - * - * @deprecated use <code>Sequence(x)</code> instead. - */ - @deprecated def single[A](x: A) = singleton(x) -} - diff --git a/src/library/scalax/collection/SizedIterable.scala b/src/library/scalax/collection/SizedIterable.scala deleted file mode 100644 index 4463c268b9..0000000000 --- a/src/library/scalax/collection/SizedIterable.scala +++ /dev/null @@ -1,38 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Collection.scala 12340 2007-07-17 15:29:47Z mcdirmid $ - - -package scalax.collection - -/** Variant of <code>Iterable</code> which also demands - * implementation of a `size` method. - * Basically, this trait just adds size to Iterable, - * and provides an optimized implementation of toArray based on it. - * - * @author Martin Odersky - * @version 2.8 - */ -trait SizedIterable[+A] extends Iterable[A] { - - /** Returns the number of elements in this collection. - * - * @return number of collection elements. - */ - def size : Int - - /** Converts this iterable to a fresh Array with <code>size</code> elements. - */ - override def toArray[B >: A]: Array[B] = { - val result = new Array[B](size) - copyToArray(result, 0) - result - } -} - diff --git a/src/library/scalax/collection/Vector.scala b/src/library/scalax/collection/Vector.scala deleted file mode 100755 index 8224a8630b..0000000000 --- a/src/library/scalax/collection/Vector.scala +++ /dev/null @@ -1,23 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $ - -package scalax.collection - -import generic._ -import mutable.ArrayBuffer -import annotation.unchecked.uncheckedVariance - -trait Vector[+A] extends Sequence[A] with VectorTemplate[Vector, A @uncheckedVariance] - -object Vector extends SequenceFactory[Vector] with EmptyIterableFactory[Vector] { - - /** The empty sequence */ - val empty : Vector[Nothing] = null // !!! todo: insert good immutable vector implementation here. -} diff --git a/src/library/scalax/collection/generic/Builder.scala b/src/library/scalax/collection/generic/Builder.scala deleted file mode 100755 index 155ca553fa..0000000000 --- a/src/library/scalax/collection/generic/Builder.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ - -package scalax.collection.generic - -import generic._ - -trait Builder[+CC[B], A] extends Growable[A] { - def +=(x: A) - def elements: Iterator[A] - def result: CC[A] - - def mapResult[DD[B]](f: CC[A] => DD[A]) = - new Builder[DD, A] with Proxy { - val self = Builder.this - def +=(x: A) = self += x - def elements: Iterator[A] = self.elements - def clear() = self.clear() - override def ++=(xs: Iterator[A]) = self ++= xs - override def ++=(xs: collection.Iterable[A]) = self ++= xs - def result: DD[A] = f(Builder.this.result) - } -} - diff --git a/src/library/scalax/collection/generic/EmptyIterableFactory.scala b/src/library/scalax/collection/generic/EmptyIterableFactory.scala deleted file mode 100755 index 7f110d13d2..0000000000 --- a/src/library/scalax/collection/generic/EmptyIterableFactory.scala +++ /dev/null @@ -1,17 +0,0 @@ -package scalax.collection.generic - -import annotation.unchecked.uncheckedVariance - -trait EmptyIterableFactory[CC[+A] <: Iterable[A] with IterableTemplate[CC, A @uncheckedVariance]] extends IterableFactory[CC] { - - /** The empty collection of type CC */ - val empty: CC[Nothing] - - /** An override of newBuilder, to work off the empty object */ - override protected def newBuilder[A]: Builder[CC, A] = - empty.newBuilder[A] - - /** Create CC collection of specified elements */ - override def apply[A](args: A*): CC[A] = - empty ++ args.asInstanceOf[Iterable[A]] -} diff --git a/src/library/scalax/collection/generic/IterableFactory.scala b/src/library/scalax/collection/generic/IterableFactory.scala deleted file mode 100755 index 0cf9c8ac95..0000000000 --- a/src/library/scalax/collection/generic/IterableFactory.scala +++ /dev/null @@ -1,122 +0,0 @@ -package scalax.collection.generic - -trait IterableFactory[CC[A] <: Iterable[A]] { - - /** Create CC collection of specified elements */ - def apply[A](args: A*): CC[A] - - protected def newBuilder[A]: Builder[CC, A] = - apply().newBuilder[A].asInstanceOf[Builder[CC, A]] - - // can't have an empty here because it is defined in subclass EmptyIterableFactory with type - // CC[Nothing]. This type does not make sense for immutable iterables. - - /** Concatenate all the argument lists into a single list. - * - * @param xss the lists that are to be concatenated - * @return the concatenation of all the lists - */ - def concat[A](xss: CC[A]*): CC[A] = { - val b = newBuilder[A] - for (xs <- xss) b ++= xs - b.result - } - - /** An iterable that contains the same element a number of times - * @param n The number of elements returned - * @param elem The element returned each time - */ - def fill[A](n: Int)(elem: => A): CC[A] = { - val b = newBuilder[A] - var i = 0 - while (i < n) { - b += elem - i += 1 - } - b.result - } - - def fill[A](n1: Int, n2: Int)(elem: => A): CC[CC[A]] = - tabulate(n1)(_ => fill(n2)(elem)) - - def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]]] = - tabulate(n1)(_ => fill(n2, n3)(elem)) - - def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]]] = - tabulate(n1)(_ => fill(n2, n3, n4)(elem)) - - def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]]] = - tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) - - def tabulate[A](n: Int)(f: Int => A): CC[A] = { - val b = newBuilder[A] - var i = 0 - while (i < n) { - b += f(i) - i += 1 - } - b.result - } - - def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] = - tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) - - def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] = - tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) - - def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]]] = - tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) - - def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]]] = - tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) - - /** Create a sequence of increasing integers in a range. - * - * @param from the start value of the sequence - * @param end the end value of the sequence - * @return the sorted list of all from `from` (inclusive) - * up to, but exclusding, `end`. - */ - def range[A](start: Int, end: Int): CC[Int] = range(start, end, 1) - - /** Create a sequence of increasing integers in a range. - * - * @param from the start value of the sequence - * @param end the end value of the sequence - * @param step the increment value of successive elements - * @return a list of values <code>from + n * step</code> for - * increasing n. If `step > 0` the sequence terminates - * with the largest value less than `end`. If `step < 0` - * the sequence terminates with the smallest value greater than `end`. - * If `step == 0`, an IllegalArgumentException is thrown. - */ - def range(start: Int, end: Int, step: Int): CC[Int] = { - if (step == 0) throw new IllegalArgumentException("zero step") - val b = newBuilder[Int] - var i = start - while ((step <= 0 || i < end) && (step >= 0 || i > end)) { - b += i - i += step - } - b.result - } - - /** Create a sequence by repeatedly applying a given function to a start value. - * - * @param start the start value of the sequence - * @param len the length of the sequence - * @param f the function that's repeatedly applied - * @return the sequence with elements <code>(start, f(start), f(f(start)), ..., f<sup>len-1</sup>(start))</code> - */ - def iterate(start: Int, len: Int)(f: Int => Int): CC[Int] = { - val b = newBuilder[Int] - var acc = start - var i = 0 - while (i < len) { - b += acc - acc = f(acc) - i += 1 - } - b.result - } -} diff --git a/src/library/scalax/collection/generic/IterableForwarder.scala b/src/library/scalax/collection/generic/IterableForwarder.scala deleted file mode 100644 index e38f030414..0000000000 --- a/src/library/scalax/collection/generic/IterableForwarder.scala +++ /dev/null @@ -1,59 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ - - -package scalax.collection.generic - -import collection.mutable.Buffer -import collection.immutable.{List, Stream} - -/** This trait implements a forwarder for iterable objects. It forwards - * all calls to a different iterable object, except for - * - * - toString, hashCode, equals, stringPrefix - * - newBuilder, view - * - all calls creating a new iterable objetc of the same kind - * - * The above methods are forwarded by subclass IterableProxy - * - * @author Martin Odersky - * @version 2.8 - */ -trait IterableForwarder[+A] extends Iterable[A] { - - /** The iterable object to which calls are forwarded */ - protected def underlying: Iterable[A] - - // Iterable delegates - // Iterable methods could be printed by cat IterableTemplate.scala | sed -n '/trait Iterable/,$ p' | egrep '^ (override )?def' - - override def elements = underlying.elements - override def isEmpty = underlying.isEmpty - override def hasDefiniteSize = underlying.hasDefiniteSize - override def foreach(f: A => Unit) = underlying.foreach(f) - override def forall(p: A => Boolean): Boolean = underlying.forall(p) - override def exists(p: A => Boolean): Boolean = underlying.exists(p) - override def count(p: A => Boolean): Int = underlying.count(p) - override def find(p: A => Boolean): Option[A] = underlying.find(p) - override def foldLeft[B](z: B)(op: (B, A) => B): B = underlying.foldLeft(z)(op) - override def foldRight[B](z: B)(op: (A, B) => B): B = underlying.foldRight(z)(op) - override def reduceLeft[B >: A](op: (B, A) => B): B = underlying.reduceLeft(op) - override def reduceRight[B >: A](op: (A, B) => B): B = underlying.reduceRight(op) - override def copyToBuffer[B >: A](dest: Buffer[B]) = underlying.copyToBuffer(dest) - override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) = underlying.copyToArray(xs, start, len) - override def toArray[B >: A]: Array[B] = underlying.toArray - override def toList: List[A] = underlying.toList - override def toSequence: Sequence[A] = underlying.toSequence - override def toStream: Stream[A] = underlying.toStream - override def mkString(start: String, sep: String, end: String): String = underlying.mkString(start, sep, end) - override def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = underlying.addString(b, start, sep, end) - - override def head: A = underlying.head -} diff --git a/src/library/scalax/collection/generic/IterableTemplate.scala b/src/library/scalax/collection/generic/IterableTemplate.scala deleted file mode 100755 index cc562c308a..0000000000 --- a/src/library/scalax/collection/generic/IterableTemplate.scala +++ /dev/null @@ -1,677 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - - -package scalax.collection.generic - -import scalax.collection.mutable.{Buffer, ArrayBuffer, ListBuffer} -import scalax.collection.immutable.{List, Nil, ::, Stream} -import util.control.Breaks._ -import Iterable._ - -/** Collection classes mixing in this class provide a method - * <code>elements</code> which returns an iterator over all the - * elements contained in the collection. - * - * @note If a collection has a known <code>size</code>, it should also sub-type <code>Collection</code>. - * Only potentially unbounded collections should directly sub-class <code>Iterable</code>. - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.8 - */ -trait IterableTemplate[+CC[/*+*/B] <: IterableTemplate[CC, B] with Iterable[B], /*+*/A] { self/*: CC[A]*/ => - - /** The template itself seen as an instance of `CC[A]`. - * @note: It would be logical to have a self type `CC[A]` instead, then we would not need - * this method. Unfortunately, tyis runs afoul some pecularities in Scala's member resolution - * algorithm: If the self type is a CC, then Iterable is one of its supertypes. Iterable - * defines a number of concrete methods such as newBuilder which are abstract here. - * The newBuilder method in Iterable[A] has type Builder[Iterable, A]. Because Scala - * prefers concrete over abstract members, it is this newBuilder which is chosen, instead of - * the abstract newBuilder in class IterableTemplate of type Builder[CC, A]. - * Even for concrete methods we have a problem because the last mixin in the parents of CC is - * Iterable, not IterableTemplate. So resolution picks the version in Iterable, which returns - * again an Iterable, not a CC, as would be required. - * These problems would be avoided if Scala computed the type of a member as the glb of the types - * all members in the class and its superclasses types. - * I think overall this would be a better design. - */ - protected[this] def thisCC: CC[A] = this.asInstanceOf[CC[A]] - - /** Creates a new iterator over all elements contained in this - * object. - * - * @return the new iterator - */ - def elements: Iterator[A] - - /** Create a new builder for this IterableType - */ - def newBuilder[B]: Builder[CC, B] - - /** Create a new builder for this IterableType - * with a hint what that its size should be size `sizeHint` - */ - def newBuilder[B](sizeHint: Int): Builder[CC, B] = newBuilder[B] - - /** Is this collection empty? */ - def isEmpty: Boolean = !elements.hasNext - - /** returns true iff this collection has a bound size. - * Many APIs in this trait will not work on collections of - * unbound sizes. - */ - def hasDefiniteSize = true - - /** Create a new iterable of type CC which contains all elements of this iterable - * followed by all elements of Iterable `that' - */ - def ++[B >: A](that: Iterable[B]): CC[B] = { - val b: Builder[CC, B] = (this: IterableTemplate[CC, A]).newBuilder[B] - b ++= thisCC - b ++= that - b.result - } - - /** Create a new iterable of type CC which contains all elements of this iterable - * followed by all elements of Iterator `that' - */ - def ++[B >: A](that: Iterator[B]): CC[B] = { - val b = newBuilder[B] - b ++= thisCC - b ++= that - b.result - } - - /** Returns the iterable resulting from applying the given function - * <code>f</code> to each element of this iterable. - * - * @param f function to apply to each element. - * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> if this - * iterable is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. - */ - def map[B](f: A => B): CC[B] = { - val b = newBuilder[B] - for (x <- this) b += f(x) - b.result - } - - /** Applies the given function <code>f</code> to each element of - * this iterable, then concatenates the results. - * - * @param f the function to apply on each element. - * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if - * this iterable is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. - */ - def flatMap[B](f: A => Iterable[B]): CC[B] = { - val b = newBuilder[B] - for (x <- this) b ++= f(x) - b.result - } - - /** Returns all the elements of this iterable that satisfy the - * predicate <code>p</code>. The order of the elements is preserved. - * @param p the predicate used to filter the iterable. - * @return the elements of this iterable satisfying <code>p</code>. - */ - def filter(p: A => Boolean): CC[A] = { - val b = newBuilder[A] - for (x <- this) - if (p(x)) b += x - b.result - } - - /** Removes all elements of the iterable which satisfy the predicate - * <code>p</code>. This is like <code>filter</code> with the - * predicate inversed. - * - * @param p the predicate to use to test elements - * @return the iterable without all elements which satisfy <code>p</code> - */ - def remove(p: A => Boolean): CC[A] = filter(!p(_)) - - /** Partitions this iterable in two iterables according to a predicate. - * - * @param p the predicate on which to partition - * @return a pair of iterables: the iterable that satisfies the predicate - * <code>p</code> and the iterable that does not. - * The relative order of the elements in the resulting iterables - * is the same as in the original iterable. - */ - def partition(p: A => Boolean): (CC[A], CC[A]) = { - val l, r = newBuilder[A] - for (x <- this) (if (p(x)) l else r) += x - (l.result, r.result) - } - - /** Apply a function <code>f</code> to all elements of this - * iterable object. - * - * @note Will not terminate for infinite-sized collections. - * @param f a function that is applied to every element. - * Note this function underlies the implementation of most other bulk operations. - * It should be overridden in concrete collectionc classes with efficient implementations. - */ - def foreach(f: A => Unit): Unit = elements.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 - */ - def forall(p: A => Boolean): Boolean = { - var result = true - breakable { - for (x <- this) - if (!p(x)) { result = false; break } - } - result - } - - /** 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 - */ - def exists(p: A => Boolean): Boolean = { - var result = false - breakable { - for (x <- this) - if (p(x)) { result = true; break } - } - result - } - - /** Count the number of elements in the iterable which satisfy a predicate. - * - * @param p the predicate for which to count - * @return the number of elements satisfying the predicate <code>p</code>. - */ - def count(p: A => Boolean): Int = { - var cnt = 0 - for (x <- this) { - if (p(x)) cnt += 1 - } - cnt - } - - /** Find and return the first element of the iterable object satisfying a - * predicate, if any. - * - * @note may 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 p the predicate - * @return an option containing the first element in the iterable object - * satisfying <code>p</code>, or <code>None</code> if none exists. - */ - def find(p: A => Boolean): Option[A] = { - var result: Option[A] = None - breakable { - for (x <- this) - if (p(x)) { result = Some(x); break } - } - result - } - - /** Combines the elements of this iterable object together using the binary - * function <code>f</code>, from left to right, and starting with - * the value <code>z</code>. - * - * @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 <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...), - * a<sub>n</sub>)</code> if the iterable is - * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>. - */ - def foldLeft[B](z: B)(op: (B, A) => B): B = { - var result = z - for (x <- this) - result = op(result, x) - result - } - - /** Combines the elements of this iterable together using the binary - * function <code>f</code>, from right to left, and starting with - * the value <code>z</code>. - * - * @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 <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code> - * if the iterable is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>. - */ - def foldRight[B](z: B)(op: (A, B) => B): B = elements.foldRight(z)(op) - - /** Similar to <code>foldLeft</code> but can be used as - * an operator with the order of iterable and zero arguments reversed. - * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code> - * @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. - */ - def /: [B](z: B)(op: (B, A) => B): B = foldLeft(z)(op) - - /** An alias for <code>foldRight</code>. - * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code> - * @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. - */ - def :\ [B](z: B)(op: (A, B) => B): B = foldRight(z)(op) - - /** Combines the elements of this iterable object together using the binary - * operator <code>op</code>, from left to right - * @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 - * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code> - if the iterable object has elements - * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>. - * @throws Predef.UnsupportedOperationException if the iterable object is empty. - */ - def reduceLeft[B >: A](op: (B, A) => B): B = { - if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft") - var result: B = elements.next - var first = true - for (x <- this) - if (first) first = false - else result = op(result, x) - result - } - - /** Combines the elements of this iterable object together using the binary - * operator <code>op</code>, 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 - * - * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code> - * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., - * a<sub>n</sub></code>. - * - * @throws Predef.UnsupportedOperationException if the iterator is empty. - */ - def reduceRight[B >: A](op: (A, B) => B): B = - elements.reduceRight(op) - - /** Returns an iterable formed from this iterable and the specified iterable - * `other` by associating each element of the former with - * the element at the same position in the latter. - * If one of the two iterables is longer than the other, its remaining elements are ignored. - */ - def zip[B](that: Iterable[B]): CC[(A, B)] = { - val these = this.elements - val those = that.elements - val b = this.newBuilder[(A, B)] - while (these.hasNext && those.hasNext) - b += ((these.next, those.next)) - b.result - } - - /** Returns a iterable formed from this iterable and the specified iterable - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * - * @param that iterable <code>that</code> may have a different length - * as the self iterable. - * @param thisElem element <code>thisElem</code> is used to fill up the - * resulting iterable if the self iterable is shorter than - * <code>that</code> -b * @param thatElem element <code>thatElem</code> is used to fill up the - * resulting iterable if <code>that</code> is shorter than - * the self iterable - * @return <code>Iterable((a<sub>0</sub>,b<sub>0</sub>), ..., - * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>), - * ..., {elem,b<sub>m</sub>})</code> - * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip - * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is - * invoked where <code>m > n</code>. - */ - def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): CC[(A1, B1)] = { - val these = this.elements - val those = that.elements - val b = newBuilder[(A1, B1)] - while (these.hasNext && those.hasNext) - b += ((these.next, those.next)) - while (these.hasNext) - b += ((these.next, thatElem)) - while (those.hasNext) - b += ((thisElem, those.next)) - b.result - } - - /** Zips this iterable with its indices. `s.zipWithIndex` is equivalent to - * `s zip s.indices`, but is usually more efficient. - */ - def zipWithIndex: CC[(A, Int)] = { - val b = newBuilder[(A, Int)] - var i = 0 - for (x <- this) { - b += ((x, i)) - i +=1 - } - b.result - } - - /** Copy all elements to a given buffer - * @note Will not terminate for infinite-sized collections. - * @param dest The buffer to which elements are copied - */ - def copyToBuffer[B >: A](dest: Buffer[B]) { - for (x <- this) dest += x - } - - /** Fills the given array <code>xs</code> with at most `len` elements of - * this iterable starting at position `start`. - * Copying will stop oce either the end of the current iterable is reached or - * `len` elements have been copied. - * - * @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 - * @pre the array must be large enough to hold all elements. - */ - def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) { - var i = start - val end = (start + len) min xs.length - for (x <- this) { - if (i < end) { - xs(i) = x - i += 1 - } - } - } - - /** Fills the given array <code>xs</code> with the elements of - * this iterable starting at position <code>start</code> - * until either the end of the current iterable or the end of array `xs` is reached. - * - * @note Will not terminate for infinite-sized collections. - * @param xs the array to fill. - * @param start starting index. - * @pre the array must be large enough to hold all elements. - */ - def copyToArray[B >: A](xs: Array[B], start: Int) { - copyToArray(xs, start, xs.length - start) - } - - /** Converts this collection to a fresh Array elements. - * @note Will not terminate for infinite-sized collections. - */ - def toArray[B >: A]: Array[B] = { - var size = 0 - for (x <- this) size += 1 - val result = new Array[B](size) - copyToArray(result, 0) - result - } - - /** - * Create a fresh list with all the elements of this iterable object. - * @note Will not terminate for infinite-sized collections. - */ - def toList: List[A] = (new ListBuffer[A] ++ thisCC).toList - - /** - * Returns a sequence containing all of the elements in this iterable object. - * @note Will not terminate for infinite-sized collections. - */ - def toSequence: Sequence[A] = toList - - /** @deprecated use toSequence instead - */ - @deprecated def toSeq: Sequence[A] = toSequence - - /** - * Create a stream which contains all the elements of this iterable object. - * @note consider using <code>projection</code> for lazy behavior. - */ - def toStream: Stream[A] = elements.toStream - - /** Sort the iterable according to the comparison function - * <code><(e1: a, e2: a) => Boolean</code>, - * which should be true iff <code>e1</code> is smaller than - * <code>e2</code>. - * The sort is stable. That is elements that are equal wrt `lt` appear in the - * same order in the sorted iterable as in the original. - * - * @param lt the comparison function - * @return a iterable sorted according to the comparison function - * <code><(e1: a, e2: a) => Boolean</code>. - * @ex <pre> - * List("Steve", "Tom", "John", "Bob") - * .sort((e1, e2) => (e1 compareTo e2) < 0) = - * List("Bob", "John", "Steve", "Tom")</pre> - * !!! - def sortWith(lt : (A,A) => Boolean): CC[A] = { - val arr = toArray - Array.sortWith(arr, lt) - val b = newBuilder[A] - for (x <- arr) b += x - b.result - } - */ - - /** Returns a string representation of this iterable object. The resulting string - * begins with the string <code>start</code> and is finished by the string - * <code>end</code>. Inside, the string representations of elements (w.r.t. - * the method <code>toString()</code>) are separated by the string - * <code>sep</code>. - * - * @ex <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code> - * @param start starting string. - * @param sep separator string. - * @param end ending string. - * @return a string representation of this iterable object. - */ - def mkString(start: String, sep: String, end: String): String = - addString(new StringBuilder(), start, sep, end).toString - - /** Returns a string representation of this iterable object. The string - * representations of elements (w.r.t. the method <code>toString()</code>) - * are separated by the string <code>sep</code>. - * - * @param sep separator string. - * @return a string representation of this iterable object. - */ - def mkString(sep: String): String = - addString(new StringBuilder(), sep).toString - - /** Converts a collection into a flat <code>String</code> by each element's toString method. - */ - def mkString = - addString(new StringBuilder()).toString - - /** Write all elements of this iterable into given string builder. - * The written text begins with the string <code>start</code> and is finished by the string - * <code>end</code>. Inside, the string representations of elements (w.r.t. - * the method <code>toString()</code>) are separated by the string - * <code>sep</code>. - */ - def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = { - b append start - var first = true - for (x <- this) { - if (first) first = false - else b append sep - b append x - } - b append end - } - - /** Write all elements of this string into given string builder. - * The string representations of elements (w.r.t. the method <code>toString()</code>) - * are separated by the string <code>sep</code>. - */ - def addString(b: StringBuilder, sep: String): StringBuilder = addString(b, "", sep, "") - - /** Write all elements of this string into given string builder without using - * any separator between consecutive elements. - */ - def addString(b: StringBuilder): StringBuilder = addString(b, "") - - /** - * returns a projection that can be used to call non-strict <code>filter</code>, - * <code>map</code>, and <code>flatMap</code> methods that build projections - * of the collection. - def projection : Iterable.Projection[A] = new Iterable.Projection[A] { - def elements = Iterable.this.elements - override def force = Iterable.this - } - */ - - override def toString = mkString(stringPrefix + "(", ", ", ")") - - /** Defines the prefix of this object's <code>toString</code> representation. - */ - def stringPrefix : String = { - var string = this.getClass.getName - val idx1 = string.lastIndexOf('.' : Int) - if (idx1 != -1) string = string.substring(idx1 + 1) - val idx2 = string.indexOf('$') - if (idx2 != -1) string = string.substring(0, idx2) - string - } - - /** Creates a view of this iterable @see IterableView - */ - def view: IterableView[CC, A] = new IterableView[CC, A] { // !!! Martin: We should maybe infer the type parameters here? - val origin = thisCC - val elements: Iterator[A] = self.elements - } - -// The following methods return non-deterministic results, unless this iterable is an OrderedIterable - - /** The first element of this iterable. - * - * @note Might return different results for different runs, unless this iterable is ordered - * @throws Predef.NoSuchElementException if the iterable is empty. - */ - def head: A = if (isEmpty) throw new NoSuchElementException else elements.next - - /** @deprecated use head instead */ - @deprecated def first: A = head - - /** Returns as an option the first element of this iterable - * or <code>None</code> if iterable is empty. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def headOption: Option[A] = if (isEmpty) None else Some(head) - - /** @deprecated use headOption instead - * <code>None</code> if iterable is empty. - */ - @deprecated def firstOption: Option[A] = headOption - - /** An iterable consisting of all elements of this iterable - * except the first one. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def tail: CC[A] = drop(1) - - /** Return an iterable consisting only of the first <code>n</code> - * elements of this iterable, or else the whole iterable, if it has less - * than <code>n</code> elements. - * - * @param n the number of elements to take - * @note Might return different results for different runs, unless this iterable is ordered - */ - def take(n: Int): CC[A] = { - val b = newBuilder[A] - var i = 0 - breakable { - for (x <- this) { - b += x - i += 1 - if (i == n) break - } - } - b.result - } - - /** Returns this iterable without its <code>n</code> first elements - * If this iterable has less than <code>n</code> elements, the empty - * iterable is returned. - * - * @param n the number of elements to drop - * @return the new iterable - * @note Might return different results for different runs, unless this iterable is ordered - */ - def drop(n: Int): CC[A] = { - val b = newBuilder[A] - var i = 0 - for (x <- this) { - if (i >= n) b += x - i += 1 - } - 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 - * @throws IndexOutOfBoundsException if <code>from < 0</code> - * or <code>length < from + len<code> - * @note Might return different results for different runs, unless this iterable is ordered - */ - def slice(from: Int, until: Int): CC[A] = { - val b = newBuilder[A] - var i = 0 - breakable { - for (x <- this) { - if (i >= from) b += x - i += 1 - if (i == until) break - } - } - b.result - } - - /** Split the iterable at a given point and return the two parts thus - * created. - * - * @param n the position at which to split - * @return a pair of iterables composed of the first <code>n</code> - * elements, and the other elements. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def splitAt(n: Int): (CC[A], CC[A]) = { - val l, r = newBuilder[A] - var i = 0 - for (x <- this) - (if (i < n) l else r) += x - (l.result, r.result) - } - - /** 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) - */ - def view(from: Int, until: Int): IterableView[CC, A] = view.slice(from, until) -} diff --git a/src/library/scalax/collection/generic/IterableView.scala b/src/library/scalax/collection/generic/IterableView.scala deleted file mode 100755 index bb111e2252..0000000000 --- a/src/library/scalax/collection/generic/IterableView.scala +++ /dev/null @@ -1,112 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - -package scalax.collection.generic - -/** A non-strict projection of an iterable. - * @author Sean McDirmid - * @author Martin Odersky - * @note this should really be a virtual class of SequenceFactory - */ -trait IterableView[+UC[/*+*/B] <: Iterable[B], /*+*/A] extends Iterable[A] { self => - - val origin: Iterable[_] - def elements: Iterator[A] - - val underlying: Iterable[_] = origin match { - case v: IterableView[t, _] => v.underlying - case _ => origin - } - - protected def isDelay = elements eq underlying.elements - - private[this] var forced: UC[A] = _ - private[this] var wasForced = false - - def force: UC[A] = { - if (!wasForced) { - forced = { - val b = underlying.newBuilder[A] - for (x <- elements) - b += x - b.result - }.asInstanceOf[UC[A]] - wasForced = true - } - forced - } - - def newBuilder[A] = underlying.newBuilder[A] - - /** Builds a new view object. This method needs to be overridden in subclasses - * which refine in IterableView type - */ - protected def newView[B](elems: Iterator[B]) = new IterableView[UC, B] { - val origin = if (self.isDelay) self.origin else self - val elements = elems - } - - /** Non-strict variant of @see IterableLike.++ */ - override def ++[B >: A](that: Iterator[B]): IterableView[UC, B] = newView(elements ++ that) - - /** Non-strict variant of @see IterableLike.++ */ - override def ++[B >: A](that: Iterable[B]): IterableView[UC, B] = newView(elements ++ that.elements) - - /** Non-strict variant of @see IterableLike.map */ - override def map[B](f: A => B): IterableView[UC, B] = newView(elements map f) - - /** Non-strict variant of @see IterableLike.flatMap */ - override def flatMap[B](f: A => Iterable[B]): IterableView[UC, B] = newView(elements flatMap (f(_).elements)) - - /** Non-strict variant of @see IterableLike.filter */ - override def filter(p: A => Boolean): IterableView[UC, A] = newView(elements filter p) - - /** Non-strict variant of @see IterableLike.partition */ - override def partition(p: A => Boolean): (IterableView[UC, A], IterableView[UC, A]) = { - val (li, ri) = elements partition p - (newView(li), newView(ri)) - } - - /** Non-strict variant of @see IterableLike.zip */ - override def zip[B](other: Iterable[B]): IterableView[UC, (A, B)] = newView(elements zip other.elements) - - /** Non-strict variant of @see IterableLike.zipWithIndex */ - override def zipWithIndex: IterableView[UC, (A, Int)] = newView(elements.zipWithIndex) - - /* Non-strict variant of @see IterableLike.zipAll - * This is not enabled because it can't be specialized in VectorView: - * VectorView is not covariant, yet must maintain updatability. Impossible to do this - * with this type signature. - override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): IterableView[UC, (A1, B1)] = - newView(elements zipAll (that.elements, thisElem, thatElem)) - */ - - /** Non-strict variant of @see Iterable.take */ - override def take(n: Int): IterableView[UC, A] = newView(elements take n) - - /** Non-strict variant of @see Iterable.drop */ - override def drop(n: Int): IterableView[UC, A] = newView(elements drop n) - - /** Non-strict variant of @see Iterable.splitAt */ - override def splitAt(n: Int): (IterableView[UC, A], IterableView[UC, A]) = (take(n), drop(n)) - - /** Non-strict variant of @see Iterable.slice */ - override def slice(from: Int, until: Int): IterableView[UC, A] = newView(elements slice (from, until)) - - /** The projection resulting from the concatenation of this projection with the <code>rest</code> projection. - * @param rest The projection that gets appended to this projection - * @deprecated Use ++ instead - */ - @deprecated def append[B >: A](rest : => Iterable[B]): IterableView[UC, B] = this ++ rest.elements - - override def stringPrefix = origin.stringPrefix+"V" - - -} diff --git a/src/library/scalax/collection/generic/LazyBuilder.scala b/src/library/scalax/collection/generic/LazyBuilder.scala deleted file mode 100755 index 74764351b6..0000000000 --- a/src/library/scalax/collection/generic/LazyBuilder.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ - -package scalax.collection.generic - -import collection.mutable.ListBuffer -import collection.immutable.{List, Nil, ::} - -abstract class LazyBuilder[+CC[B], A] extends Builder[CC, A] { - protected var parts = new ListBuffer[Iterator[A]] - def +=(x: A) = { parts += Iterator.single(x) } - override def ++=(xs: Iterator[A]) { parts += xs } - override def ++=(xs: Iterable[A]) { parts += xs.elements } - def elements: Iterator[A] = Iterator.iteratorIteratorWrapper(parts.elements).flatten // !!! can remove the wrapper once new compiler is in starr - def result: CC[A] - def clear() { parts.clear() } -} diff --git a/src/library/scalax/collection/generic/MapFactory.scala b/src/library/scalax/collection/generic/MapFactory.scala deleted file mode 100755 index d7413b8928..0000000000 --- a/src/library/scalax/collection/generic/MapFactory.scala +++ /dev/null @@ -1,9 +0,0 @@ -package scalax.collection.generic - -trait MapFactory[CC[A, B] <: MapTemplate[A, B, CC]] { - - def empty[A, B]: CC[A, B] - - def apply[A, B](elems: (A, B)*): CC[A, B] = empty[A, B] ++ elems.asInstanceOf[Iterable[(A, B)]] // !@! - -} diff --git a/src/library/scalax/collection/generic/MapView.scala b/src/library/scalax/collection/generic/MapView.scala deleted file mode 100644 index 924fd1173e..0000000000 --- a/src/library/scalax/collection/generic/MapView.scala +++ /dev/null @@ -1,44 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - -package scalax.collection.generic - -/** A non-strict view of a map. - * @author Martin Odersky - * @version 2.8 - */ -trait MapView[+UC[A1, B1] <: MapTemplate[A1, B1, UC] with Map[A1, B1], A, B] extends Map[A, B] { self => - - val origin: Map[A, _] - - def empty[C] = origin.empty[C] - - def elements: Iterator[(A, B)] - - val underlying: Map[A, _] = origin match { - case v: MapView[t, _, _] => v.underlying - case _ => origin - } - private[this] var forced: UC[A, B] = _ - private[this] var wasForced = false - - def force: UC[A, B] = { - if (!wasForced) { - forced = underlying.empty[B].asInstanceOf[UC[A, B]] ++ elements - wasForced = true - } - forced - } - - def update (key: A, value: B): UC[A, B] = force update (key, value) - def - (key: A): UC[A, B] = force - key -} - - diff --git a/src/library/scalax/collection/generic/MutableVectorTemplate.scala b/src/library/scalax/collection/generic/MutableVectorTemplate.scala deleted file mode 100755 index 71c3f7bdf8..0000000000 --- a/src/library/scalax/collection/generic/MutableVectorTemplate.scala +++ /dev/null @@ -1,56 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $ - -package scalax.collection.generic - -import collection.mutable.Vector -import collection.mutable.Vector._ - -/** Sequences that support O(1) element access and O(1) length computation. - * plus an update operation. - * @author Sean McDirmid - * @author Martin Odersky - * @version 2.8 - */ -trait MutableVectorTemplate[+CC[B] <: MutableVectorTemplate[CC, B] with Vector[B], A] extends VectorTemplate[CC, A] { -self => - - def update(idx: Int, elem: A) - - /** Creates a view of this iterable @see OrderedIterable.View - */ - override def view: MutableVectorView[CC, A] = new MutableVectorView[CC, A] { // !!! Martin: We should maybe infer the type parameters here? - val origin: Vector[_] = thisCC - val length: Int = self.length - def apply(idx: Int): A = self.apply(idx) - def update(idx: Int, elem: A) = self.update(idx, elem) - } - - /** A sub-sequence 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 sequence, whereas `slice` produces a new sequence. - * - * @note view(from, to) is equivalent to view.slice(from, to) - */ - override def view(from: Int, until: Int): MutableVectorView[CC, A] = view.slice(from, until) - - def readOnly: collection.Vector[A] = new collection.Vector[A] { //!!! just use a VectorProxy? - def length = self.length - def apply(idx : Int) = self.apply(idx) - def newBuilder[B]: Builder[collection.Vector, B] = self.newBuilder[B] //mapResult (_.readOnly) - override def foreach(f: A => Unit) = self.foreach(f) - override def stringPrefix = self.stringPrefix+"RO" - } -} - diff --git a/src/library/scalax/collection/generic/MutableVectorView.scala b/src/library/scalax/collection/generic/MutableVectorView.scala deleted file mode 100755 index d445ba336e..0000000000 --- a/src/library/scalax/collection/generic/MutableVectorView.scala +++ /dev/null @@ -1,97 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ - - -package scalax.collection.generic - -import collection.mutable.Vector -import collection.mutable.Vector._ - -/** A non-strict projection of an iterable. - * @author Sean McDirmid - * @author Martin Odersky - * @note this should really be a virtual class of SequenceFactory - */ -trait MutableVectorView[+UC[B] <: Vector[B], A] extends SequenceView[UC, A] with Vector[A] { -self => - - /** refined from Iterable.View */ - val origin: Vector[_] - - override def newBuilder[A] = underlying.newBuilder[A].asInstanceOf[Builder[Vector, A]] - - trait Transformed[B] extends super.Transformed[B] with MutableVectorView[UC, B] { - override val origin = self - override def elements: Iterator[B] = new Elements(0, length) - override protected def asCC = asInstanceOf[MutableVectorView[UC, B]] - } - - class Appended(that: Vector[A]) extends super.Appended[A](that) with Transformed[A] { - override def update(idx: Int, elem: A) { - val ll = self.length - if (idx < ll) self.update(idx, elem) else that.update(idx - ll, elem) - } - } - - class Sliced(from: Int, to: Int) extends super.Sliced(from, to) with Transformed[A] { - override def update(idx: Int, elem: A) { - if (idx >= 0 && idx < length) self.update(idx + from, elem) - else throw new IndexOutOfBoundsException(idx.toString) - } - override def slice(from1: Int, to1: Int) = - new self.Sliced(from + (from1 min length max 0) , to + (to1 min length max 0)) - } - - class Reversed extends super.Reversed with Transformed[A] { - override def update(idx: Int, elem: A) { - self.update(length - 1 - idx, elem) - } - } - - class Zipped[B](that: Vector[B]) extends super.Zipped[B](that) with Transformed[(A, B)] { - override def update(idx: Int, elem: (A, B)) { - self.update(idx, elem._1) - that.update(idx, elem._2) - } - } - - def ++(that: Vector[A]): MutableVectorView[UC, A] = - new Appended(that).asCC - - override def reverse: MutableVectorView[UC, A] = - (new Reversed).asCC - - private def toVector[B](xs: Iterable[B]): Vector[B] = xs match { - case ras: Vector[_] => ras.asInstanceOf[Vector[B]] - case _ => Vector() ++ xs - } - - override def zip[B](that: Iterable[B]): MutableVectorView[UC, (A, B)] = - new Zipped(toVector(that)).asCC - - override def zipWithIndex: MutableVectorView[UC, (A, Int)] = - zip((0 until length).asInstanceOf[Null]) // !@! - override def take(n: Int): MutableVectorView[UC, A] = - slice(0, n) - override def drop(n: Int): MutableVectorView[UC, A] = - slice(n, Math.MAX_INT) - override def splitAt(n: Int): (MutableVectorView[UC, A], MutableVectorView[UC, A]) = (take(n), drop(n)) - override def slice(from: Int, until: Int): MutableVectorView[UC, A] = - new Sliced(from, until).asCC - override def takeWhile(p: A => Boolean): MutableVectorView[UC, A] = - take(prefixLength(p)) - override def dropWhile(p: A => Boolean): MutableVectorView[UC, A] = - drop(prefixLength(p)) - override def span(p: A => Boolean): (MutableVectorView[UC, A], MutableVectorView[UC, A]) = { - val n = prefixLength(p) - (take(n), drop(n)) - } -} - diff --git a/src/library/scalax/collection/generic/OrderedIterableTemplate.scala b/src/library/scalax/collection/generic/OrderedIterableTemplate.scala deleted file mode 100755 index 501cbf6447..0000000000 --- a/src/library/scalax/collection/generic/OrderedIterableTemplate.scala +++ /dev/null @@ -1,161 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - - -package scalax.collection.generic - -import OrderedIterable._ - -import util.control.Breaks._ - -/** Ordered iterables are iterables where the `elements` method always returns elements in the same - * order (namely the order in which elements were appended to the iterable). In particular, one has - * for every two ordered iterables `xs` and `ys`: - * - * `(xs ++ ys).elements = xs.elements ++ ys.elements - */ -trait OrderedIterableTemplate[+CC[/*+*/B] <: OrderedIterableTemplate[CC, B] with OrderedIterable[B], /*+*/A] - extends IterableTemplate[CC, A] { - - /** The last element of this iterable. - * - * @throws Predef.NoSuchElementException if the iterable is empty. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def last: A = { - var lst = head - for (x <- this) - lst = x - lst - } - - /** Returns as an option the last element of this iterable or - * <code>None</code> if iterable is empty. - * - * @return the last element as an option. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def lastOption: Option[A] = if (isEmpty) None else Some(last) - - /** An iterable consisting of all elements of this iterable except the last one. - * @throws Predef.UnsupportedOperationException if the stream is empty. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def init: CC[A] = { - if (isEmpty) throw new UnsupportedOperationException("empty.init") - var lst = head - val b = newBuilder[A] - for (x <- this) { - b += lst - lst = x - } - b.result - } - - /** Returns the rightmost <code>n</code> elements from this iterable. - * - * @param n the number of elements to take - * @note Might return different results for different runs, unless this iterable is ordered - */ - def takeRight(n: Int): CC[A] = { - val b = newBuilder[A] - val lead = elements drop n - var go = false - for (x <- this) { - if (go) b += x - else if (lead.hasNext) lead.next - else go = true - } - b.result - } - - /** Returns the iterable wihtout its rightmost <code>n</code> elements. - * - * @param n the number of elements to take - * @note Might return different results for different runs, unless this iterable is ordered - */ - def dropRight(n: Int): CC[A] = { - val b = newBuilder[A] - val lead = elements drop n - breakable { - for (x <- this) { - if (!lead.hasNext) break - lead.next - b += x - } - } - b.result - } - - /** Returns the longest prefix of this iterable whose elements satisfy - * the predicate <code>p</code>. - * - * @param p the test predicate. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def takeWhile(p: A => Boolean): CC[A] = { - val b = newBuilder[A] - breakable { - for (x <- this) { - if (!p(x)) break - b += x - } - } - b.result - } - - /** Returns the longest suffix of this iterable whose first element - * does not satisfy the predicate <code>p</code>. - * - * @param p the test predicate. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def dropWhile(p: A => Boolean): CC[A] = { - val b = newBuilder[A] - var go = false - for (x <- this) { - if (go) b += x - else if (!p(x)) { go = true; b += x } - } - b.result - } - - /** Returns a pair consisting of the longest prefix of the iterable whose - * elements all satisfy the given predicate, and the rest of the iterable. - * - * @param p the test predicate - * @return a pair consisting of the longest prefix of the iterable whose - * elements all satisfy <code>p</code>, and the rest of the iterable. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def span(p: A => Boolean): (CC[A], CC[A]) = { - val l, r = newBuilder[A] - var toLeft = true - for (x <- this) { - toLeft = toLeft && p(x) - (if (toLeft) l else r) += x - } - (l.result, r.result) - } - - /** Checks if the other iterable object contains the same elements as this one. - * - * @note will not terminate for infinite-sized iterables. - * @param that the other iterable - * @return true, iff both iterables contain the same elements. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def sameElements[B >: A](that: OrderedIterable[B]): Boolean = { - val these = this.elements - val those = that.elements - while (these.hasNext && those.hasNext && these.next() == those.next()) {} - !these.hasNext && !those.hasNext - } -} diff --git a/src/library/scalax/collection/generic/OrderedIterableView.scala b/src/library/scalax/collection/generic/OrderedIterableView.scala deleted file mode 100755 index 9f0d981f54..0000000000 --- a/src/library/scalax/collection/generic/OrderedIterableView.scala +++ /dev/null @@ -1,87 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - -package scalax.collection.generic - -/** A non-strict projection of an iterable. - * @author Sean McDirmid - * @author Martin Odersky - * @note this should really be a virtual class of SequenceFactory - */ -trait OrderedIterableView[+UC[/*+*/B] <: Iterable[B], /*+*/A] extends IterableView[UC, A] with OrderedIterable[A] { self => - - val origin: OrderedIterable[_] - - override def newBuilder[A] = underlying.newBuilder[A].asInstanceOf[Builder[OrderedIterable, A]] - - /** Builds a new view object. This method needs to be overridden in subclasses - * which refine in IterableView type - */ - protected override def newView[B](elems: Iterator[B]) = new OrderedIterableView[UC, B] { - val origin = if (self.isDelay) self.origin else self - val elements = elems - } - - /** Non-strict variant of @see IterableLike.++ */ - override def ++[B >: A](that: Iterator[B]): OrderedIterableView[UC, B] = newView(elements ++ that) - - /** Non-strict variant of @see IterableLike.++ */ - override def ++[B >: A](that: Iterable[B]): OrderedIterableView[UC, B] = newView(elements ++ that.elements) - - /** Non-strict variant of @see IterableLike.map */ - override def map[B](f: A => B): OrderedIterableView[UC, B] = newView(elements map f) - - /** Non-strict variant of @see IterableLike.flatMap */ - override def flatMap[B](f: A => Iterable[B]): OrderedIterableView[UC, B] = newView(elements flatMap (f(_).elements)) - - /** Non-strict variant of @see IterableLike.filter */ - override def filter(p: A => Boolean): OrderedIterableView[UC, A] = newView(elements filter p) - - /** Non-strict variant of @see IterableLike.partition */ - override def partition(p: A => Boolean): (OrderedIterableView[UC, A], OrderedIterableView[UC, A]) = { - val (li, ri) = elements partition p - (newView(li), newView(ri)) - } - - /** Non-strict variant of @see IterableLike.zip */ - override def zip[B](other: Iterable[B]): OrderedIterableView[UC, (A, B)] = newView(elements zip other.elements) - - /** Non-strict variant of @see IterableLike.zipWithIndex */ - override def zipWithIndex: OrderedIterableView[UC, (A, Int)] = newView(elements.zipWithIndex) - - /* Non-strict variant of @see IterableLike.zipAll - * This is not enabled because it can't be specialized in VectorView: - * VectorView is not covariant, yet must maintain updatability. Impossible to do this - * with this type signature. - override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): OrderedIterableView[UC, (A1, B1)] = - newView(elements zipAll (that.elements, thisElem, thatElem)) - */ - - /** Non-strict variant of @see Iterable.take */ - override def take(n: Int): OrderedIterableView[UC, A] = newView(elements take n) - - /** Non-strict variant of @see Iterable.drop */ - override def drop(n: Int): OrderedIterableView[UC, A] = newView(elements drop n) - - /** Non-strict variant of @see Iterable.splitAt */ - override def splitAt(n: Int): (OrderedIterableView[UC, A], OrderedIterableView[UC, A]) = (take(n), drop(n)) - - /** Non-strict variant of @see Iterable.slice */ - override def slice(from: Int, until: Int): OrderedIterableView[UC, A] = newView(elements slice (from, until)) - - /** Non-strict variant of @see Iterable.takeWhile */ - override def takeWhile(p: A => Boolean): OrderedIterableView[UC, A] = newView(elements takeWhile p) - - /** Non-strict variant of @see Iterable.dropWhile */ - override def dropWhile(p: A => Boolean): OrderedIterableView[UC, A] = newView(elements dropWhile p) - - /** Non-strict variant of @see Iterable.span */ - override def span(p: A => Boolean): (OrderedIterableView[UC, A], OrderedIterableView[UC, A]) = (takeWhile(p), dropWhile(p)) -} diff --git a/src/library/scalax/collection/generic/SequenceView.scala b/src/library/scalax/collection/generic/SequenceView.scala deleted file mode 100755 index 4f70f8a9d8..0000000000 --- a/src/library/scalax/collection/generic/SequenceView.scala +++ /dev/null @@ -1,131 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ - - -package scalax.collection.generic - -import util.control.Breaks._ -import annotation.unchecked.uncheckedVariance - -import Sequence._ - -/** A non-strict projection of an iterable. - * @author Sean McDirmid - * @author Martin Odersky - * @note this should really be a virtual class of SequenceFactory - */ -trait SequenceView[+UC[/*+*/B] <: Sequence[B], /*+*/A] extends IterableView[UC, A] with Sequence[A] { -self => - - /** refined from Iterable.View */ - val origin: Sequence[_] - - override def newBuilder[A] = underlying.newBuilder[A].asInstanceOf[Builder[Sequence, A]] - - trait Transformed[/*+*/B] extends SequenceView[UC, B] { - val origin = self - protected def asCC = asInstanceOf[SequenceView[UC, B]] - } - - class Appended[/*+*/B >: A](that: Sequence[B]) extends Transformed[B] { - override def elements: Iterator[B] = self.elements ++ that.elements - override def length: Int = self.length + that.length - override def apply(idx: Int): B = { - val ll = self.length - if (idx < ll) self.apply(idx) else that.apply(idx - ll) - } - override def stringPrefix = self.stringPrefix + "A" - } - - class Sliced(from: Int, to: Int) extends Transformed[A] { - override def elements: Iterator[A] = self.elements slice (from, to) - override lazy val length: Int = ((to min self.length) - (from max 0) min 0) - override def apply(idx: Int): A = - if (idx >= 0 && idx < length) self.apply(idx + from) - else throw new IndexOutOfBoundsException(idx.toString) - override def stringPrefix = self.stringPrefix + "S" - override def slice(from1: Int, to1: Int) = - new self.Sliced(from + (from1 min length max 0) , to + (to1 min length max 0)).asInstanceOf[SequenceView[UC, A]] - } - - class Mapped[/*+*/B](f: A => B) extends Transformed[B] { - override def elements: Iterator[B] = self.elements map f - override def length: Int = self.length - override def apply(idx: Int): B = f(self.apply(idx)) - override def stringPrefix = self.stringPrefix + "M" - } - - class Reversed extends Transformed[A] { - override def elements: Iterator[A] = self.reversedElements - override def length: Int = self.length - override def apply(idx: Int): A = self.apply(length - 1 - idx) - override def stringPrefix = super.stringPrefix+"R" - } - - class Patched[/*+*/B >: A](from: Int, patch: Sequence[B], replaced: Int) extends Transformed[B] { - val plen = patch.length - override def elements: Iterator[B] = self.elements patch (from, patch, replaced) - override def length: Int = self.length + plen - replaced - override def apply(idx: Int): B = - if (idx < from) self.apply(idx) - else if (idx < from + plen) patch.apply(idx - from) - else self.apply(idx - plen + replaced) - override def stringPrefix = super.stringPrefix+"P" - } - - class Zipped[/*+*/B](that: Sequence[B]) extends Transformed[(A, B)] { - override def elements: Iterator[(A, B)] = self.elements zip that.elements - override def length = self.length min that.length - override def apply(idx: Int): (A, B) = (self.apply(idx), that.apply(idx)) - override def stringPrefix = super.stringPrefix+"Z" - } - - override def ++[B >: A](that: Iterable[B]): SequenceView[UC, B] = - new Appended[B](that.toSequence).asCC - override def ++[B >: A](that: Iterator[B]): SequenceView[UC, B] = - new Appended[B](that.toSequence).asCC - override def map[B](f: A => B): SequenceView[UC, B] = - new Mapped(f).asCC - override def reverse: SequenceView[UC, A] = - (new Reversed).asCC - def patch[B >: A](from: Int, patch: Sequence[B], replaced: Int): SequenceView[UC, B] = - if (0 <= from && from < length) new Patched(from, patch, replaced).asCC - else throw new IndexOutOfBoundsException(from.toString) - override def padTo[B >: A](len: Int, elem: B): SequenceView[UC, B] = - patch(length, fill((len - length) max 0)(elem), 0) - override def zip[B](that: Iterable[B]): SequenceView[UC, (A, B)] = - new Zipped(that.toSequence).asCC - override def zipWithIndex: SequenceView[UC, (A, Int)] = - zip((0 until length).asInstanceOf[Null]) // !@! - /* - override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): SequenceView[UC, (A1, B1)] = { - val that1 = that.toSequence - self.padTo(that1.length, thisElem) zip that1.padTo(this.length, thatElem)//.asInstanceOf[SequenceView[UC, (A1, B1)]] - }*/ - override def take(n: Int): SequenceView[UC, A] = - slice(0, n) - override def drop(n: Int): SequenceView[UC, A] = - slice(n, Math.MAX_INT) - override def splitAt(n: Int): (SequenceView[UC, A], SequenceView[UC, A]) = (take(n), drop(n)) - override def slice(from: Int, until: Int): SequenceView[UC, A] = - new Sliced(from, until).asCC - override def takeWhile(p: A => Boolean): SequenceView[UC, A] = - take(prefixLength(p)) - override def dropWhile(p: A => Boolean): SequenceView[UC, A] = - drop(prefixLength(p)) - override def span(p: A => Boolean): (SequenceView[UC, A], SequenceView[UC, A]) = { - val n = prefixLength(p) - (take(n), drop(n)) - } - - // missing here because we can't do anything about them, so we fall back to default construction - // if an IterableView via newView: flatMap, filter, partition -} - diff --git a/src/library/scalax/collection/generic/SetFactory.scala b/src/library/scalax/collection/generic/SetFactory.scala deleted file mode 100644 index 458d4bbade..0000000000 --- a/src/library/scalax/collection/generic/SetFactory.scala +++ /dev/null @@ -1,11 +0,0 @@ -package scalax.collection.generic - -trait SetFactory[CC[A] <: SetTemplate[CC, A] with Set[A]] extends IterableFactory[CC] { - - def empty[A]: CC[A] - - def apply[A](elems: A*): CC[A] = empty[A] ++ elems.asInstanceOf[Iterable[A]] // !@! - - override def newBuilder[B]: Builder[CC, B] = new AddableBuilder[CC, B](empty) - -} diff --git a/src/library/scalax/collection/generic/VectorTemplate.scala b/src/library/scalax/collection/generic/VectorTemplate.scala deleted file mode 100644 index d97fd03aa4..0000000000 --- a/src/library/scalax/collection/generic/VectorTemplate.scala +++ /dev/null @@ -1,266 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $ - -package scalax.collection.generic - -import Vector._ - -/** Sequences that support O(1) element access and O(1) length computation. - * @author Sean McDirmid - * @author Martin Odersky - * @version 2.8 - */ -trait VectorTemplate[+CC[/*+*/B] <: VectorTemplate[CC, B] with Vector[B], /*+*/A] extends SequenceTemplate[CC, A] { -self => - - // Overridden methods from IterableTemplate - - /** The iterator returned by the elements method - */ - protected class Elements(start: Int, end: Int) extends scalax.collection.BufferedIterator[A] { - var i = start - def hasNext: Boolean = i < end - def next: A = - if (i < end) { - val x = self(i) - i += 1 - x - } else Iterator.empty.next - def head = - if (i < end) self(i) else Iterator.empty.next - /** drop is overridden to enable fast searching in the middle of random access sequences */ - override def drop(n: Int): Iterator[A] = - if (n > 0) new Elements(start + n, end) else this - /** is overridden to be symmetric to drop */ - override def take(n: Int): Iterator[A] = - if (n < 0) Iterator.empty.buffered - else if (start + n < end) new Elements(start, start + n) - else this - } - - override def elements: Iterator[A] = new Elements(0, length) - - override def isEmpty: Boolean = { length == 0 } - - override def foreach(f: A => Unit): Unit = { - var i = 0 - val len = length - while (i < len) { f(this(i)); i += 1 } - } - - override def forall(p: A => Boolean): Boolean = prefixLength(p(_)) == length - override def exists(p: A => Boolean): Boolean = prefixLength(!p(_)) != length - - override def find(p: A => Boolean): Option[A] = { - val i = prefixLength(!p(_)) - if (i < length) Some(this(i)) else None - } - - private def foldl[B](start: Int, z: B, op: (B, A) => B): B = { - var i = start - val len = length - var result = z - while (i < len) { - result = op(result, this(i)) - i += 1 - } - result - } - - private def foldr[B](start: Int, len: Int, z: B, op: (A, B) => B): B = - if (start == len) z - else op(this(start), foldr(start + 1, len, z, op)) - - override def foldLeft[B](z: B)(op: (B, A) => B): B = foldl(0, z, op) - override def foldRight[B](z: B)(op: (A, B) => B): B = foldr(0, length, z, op) - override def reduceLeft[B >: A](op: (B, A) => B): B = - if (length > 0) foldl(0, this(0), op) else super.reduceLeft(op) - override def reduceRight[B >: A](op: (A, B) => B): B = - if (length > 0) foldr(0, length - 1, this(length - 1), op) else super.reduceRight(op) - - override def zip[B](that: Iterable[B]): CC[(A, B)] = that match { - case that: Vector[_] => - var i = 0 - val len = this.length min that.length - val b = this.newBuilder[(A, B)](len) - while (i < len) { - b += ((this(i), that(i).asInstanceOf[B])) - i += 1 - } - b.result - case _ => - super.zip(that) - } - - override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): CC[(A1, B1)] = that match { - case that: Vector[_] => - var i = 0 - val thisLen = this.length - val thatLen = that.length - val len = thisLen min thatLen - val b = this.newBuilder[(A1, B1)](thisLen max thatLen) - while (i < len) { - b += ((this(i), that(i).asInstanceOf[B])) - i += 1 - } - while (i < this.length) { - b += ((this(i), thatElem)) - i += 1 - } - while (i < that.length) { - b += ((this(i), thatElem.asInstanceOf[B])) - i += 1 - } - b.result - case _ => - super.zipAll(that, thisElem, thatElem) - } - - override def zipWithIndex: CC[(A, Int)] = { - val len = length - val b = newBuilder[(A, Int)](len) - var i = 0 - while (i < len) { - b += ((this(i), i)) - i += 1 - } - b.result - } - - override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) { - var i = 0 - var j = start - val end = length min len min (xs.length - start) - while (i < end) { - xs(j) = this(i) - i += 1 - j += 1 - } - } - - // Overridden methods from OrderedIterableTemplate - - override def head: A = if (isEmpty) throw new NoSuchElementException else this(0) - - override def slice(from: Int, until: Int): CC[A] = { - var i = from max 0 - val end = until min length - val b = newBuilder[A](end - i) - while (i < end) { - b += this(i) - i += 1 - } - b.result - } - - override def take(n: Int): CC[A] = slice(0, n) - override def drop(n: Int): CC[A] = slice(n, length) - override def takeRight(n: Int): CC[A] = slice(length - n, length) - override def dropRight(n: Int): CC[A] = slice(0, length - n) - override def splitAt(n: Int): (CC[A], CC[A]) = (take(n), drop(n)) - override def takeWhile(p: A => Boolean): CC[A] = take(prefixLength(p)) - override def dropWhile(p: A => Boolean): CC[A] = drop(prefixLength(p)) - override def span(p: A => Boolean): (CC[A], CC[A]) = splitAt(prefixLength(p)) - override def last: A = if (length > 0) this(length - 1) else super.last - override def init: CC[A] = if (length > 0) slice(0, length - 1) else super.init - - override def sameElements[B >: A](that: OrderedIterable[B]): Boolean = that match { - case that: Vector[_] => - val len = length - len == that.length && { - var i = 0 - while (i < len && this(i) == that(i)) i += 1 - i == len - } - case _ => - super.sameElements(that) - } - - // Overridden methods from Sequence - - override def lengthCompare(len: Int): Int = length - len - - private def negLength(n: Int) = if (n == length) -1 else n - - override def indexWhere(p: A => Boolean, from: Int): Int = - negLength(from + segmentLength(!p(_), from)) - - override def lastIndexWhere(p: A => Boolean, end: Int): Int = { - var i = end - while (i >= 0 && !p(this(i))) i -= 1 - i - } - - override def lastIndexOf[B >: A](elem: B, end: Int): Int = lastIndexWhere(elem ==, end) - - override def reverse: CC[A] = { - val b = newBuilder[A](length) - var i = length - while (0 < i) { - i -= 1 - b += this(i) - } - b.result - } - - override def reversedElements: Iterator[A] = new Iterator[A] { - var i = length - def hasNext: Boolean = 0 < i - def next: A = - if (0 < i) { - i -= 1 - self(i) - } else Iterator.empty.next - } - - override def startsWith[B](that: Sequence[B], offset: Int): Boolean = that match { - case that: Vector[_] => - var i = offset - var j = 0 - val thisLen = length - val thatLen = that.length - while (i < thisLen && j < thatLen && this(i) == that(j)) { - i += 1 - j += 1 - } - j == thatLen - case _ => - var i = offset - val thisLen = length - val thatElems = that.elements - while (i < thisLen && thatElems.hasNext && this(i) == thatElems.next) { - i += 1 - } - !thatElems.hasNext - } - - override def endsWith[B](that: Sequence[B]): Boolean = that match { - case that: Vector[_] => - val thisLen = length - val thatLen = that.length - var i = thisLen - 1 - var j = thatLen - 1 - while (i >= 0 && j >= 0 && this(i) == that(j)) { - i -= 1 - j -= 1 - } - j == 0 - case _ => - super.endsWith(that) - } - - override def indexOf[B >: A](that: Sequence[B]): Int = { - var i = 0 - val last = length - that.length - while (i <= last && !startsWith(that, i)) i += 1 - negLength(i) - } -} - diff --git a/src/library/scalax/collection/generic/covartest/IterableFactory.scala b/src/library/scalax/collection/generic/covartest/IterableFactory.scala deleted file mode 100755 index d12da89987..0000000000 --- a/src/library/scalax/collection/generic/covartest/IterableFactory.scala +++ /dev/null @@ -1,108 +0,0 @@ -package scalax.collection.generic.covartest - -trait IterableFactory[CC[A] <: Iterable[A]] { - - /** Create CC collection of specified elements */ - def apply[A](args: A*): CC[A] - - protected def newBuilder[A]: Builder[CC, A] = - apply().newBuilder[A].asInstanceOf[Builder[CC, A]] - - /** Concatenate all the argument lists into a single list. - * - * @param xss the lists that are to be concatenated - * @return the concatenation of all the lists - */ - def concat[A](xss: CC[A]*): CC[A] = { - val b = newBuilder[A] - for (xs <- xss) b ++= xs - b.result - } - - /** An iterable that contains the same element a number of times - * @param n The number of elements returned - * @param elem The element returned each time - */ - def fill[A](n: Int, elem: => A): CC[A] = { - val b = newBuilder[A] - var i = 0 - while (i < n) { - b += elem - i += 1 - } - b.result - } - - def fill[A](n1: Int, n2: Int, elem: => A): CC[CC[A]] = - tabulate(n1)(_ => fill(n2, elem)) - - def fill[A](n1: Int, n2: Int, n3: Int, elem: => A): CC[CC[CC[A]]] = - tabulate(n1)(_ => fill(n2, n3, elem)) - - def tabulate[A](n: Int)(f: Int => A): CC[A] = { - val b = newBuilder[A] - var i = 0 - while (i < n) { - b += f(i) - i += 1 - } - b.result - } - - def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] = - tabulate(n1)(i1 => tabulate(n2)(i2 => f(i1, i2))) - - def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] = - tabulate(n1)(i1 => tabulate(n2)(i2 => tabulate(n3)(i3 => f(i1, i2, i3)))) -// todo: go up to 5(?) - - /** Create a sequence of increasing integers in a range. - * - * @param from the start value of the sequence - * @param end the end value of the sequence - * @return the sorted list of all from `from` (inclusive) - * up to, but exclusding, `end`. - */ - def range[A](start: Int, end: Int): CC[Int] = range(start, end, 1) - - /** Create a sequence of increasing integers in a range. - * - * @param from the start value of the sequence - * @param end the end value of the sequence - * @param step the increment value of successive elements - * @return a list of values <code>from + n * step</code> for - * increasing n. If `step > 0` the sequence terminates - * with the largest value less than `end`. If `step < 0` - * the sequence terminates with the smallest value greater than `end`. - * If `step == 0`, the sequence gors on infinitely (in that - * case the `range` operation might not terminate. - */ - def range(start: Int, end: Int, step: Int): CC[Int] = { - val b = newBuilder[Int] - var i = start - while ((step <= 0 || i < end) && (step >= 0 || i > end)) { - b += i - i += step - } - b.result - } - - /** Create a sequence by repeatedly applying a given function to a start value. - * - * @param start the start value of the sequence - * @param len the length of the sequence - * @param f the function that's repeatedly applied - * @return the sequence with elements <code>(start, f(start), f(f(start)), ..., f<sup>len-1</sup>(start))</code> - */ - def iterate(start: Int, len: Int)(f: Int => Int): CC[Int] = { - val b = newBuilder[Int] - var acc = start - var i = 0 - while (i < len) { - b += acc - acc = f(acc) - i += 1 - } - b.result - } -} diff --git a/src/library/scalax/collection/generic/covartest/IterableTemplate.scala b/src/library/scalax/collection/generic/covartest/IterableTemplate.scala deleted file mode 100755 index 791d698a75..0000000000 --- a/src/library/scalax/collection/generic/covartest/IterableTemplate.scala +++ /dev/null @@ -1,677 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - - -package scalax.collection.generic.covartest - -import scalax.collection.mutable.{Buffer, ArrayBuffer, ListBuffer} -import scalax.collection.immutable.{List, Nil, ::, Stream} -import util.control.Breaks._ -import Iterable._ - -/** Collection classes mixing in this class provide a method - * <code>elements</code> which returns an iterator over all the - * elements contained in the collection. - * - * @note If a collection has a known <code>size</code>, it should also sub-type <code>Collection</code>. - * Only potentially unbounded collections should directly sub-class <code>Iterable</code>. - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.8 - */ -trait IterableTemplate[+CC[+B] <: IterableTemplate[CC, B] with Iterable[B], +A] { self/*: CC[A]*/ => - - /** The template itself seen as an instance of `CC[A]`. - * @note: It would be logical to have a self type `CC[A]` instead, then we would not need - * this method. Unfortunately, tyis runs afoul some pecularities in Scala's member resolution - * algorithm: If the self type is a CC, then Iterable is one of its supertypes. Iterable - * defines a number of concrete methods such as newBuilder which are abstract here. - * The newBuilder method in Iterable[A] has type Builder[Iterable, A]. Because Scala - * prefers concrete over abstract members, it is this newBuilder which is chosen, instead of - * the abstract newBuilder in class IterableTemplate of type Builder[CC, A]. - * Even for concrete methods we have a problem because the last mixin in the parents of CC is - * Iterable, not IterableTemplate. So resolution picks the version in Iterable, which returns - * again an Iterable, not a CC, as would be required. - * These problems would be avoided if Scala computed the type of a member as the glb of the types - * all members in the class and its superclasses types. - * I think overall this would be a better design. - */ - protected[this] def thisCC: CC[A] = this.asInstanceOf[CC[A]] - - /** Creates a new iterator over all elements contained in this - * object. - * - * @return the new iterator - */ - def elements: Iterator[A] - - /** Create a new builder for this IterableType - */ - def newBuilder[B]: Builder[CC, B] - - /** Create a new builder for this IterableType - * with a hint what that its size should be size `sizeHint` - */ - def newBuilder[B](sizeHint: Int): Builder[CC, B] = newBuilder[B] - - /** Is this collection empty? */ - def isEmpty: Boolean = !elements.hasNext - - /** returns true iff this collection has a bound size. - * Many APIs in this trait will not work on collections of - * unbound sizes. - */ - def hasDefiniteSize = true - - /** Create a new iterable of type CC which contains all elements of this iterable - * followed by all elements of Iterable `that' - */ - def ++[B >: A](that: Iterable[B]): CC[B] = { - val b: Builder[CC, B] = (this: IterableTemplate[CC, A]).newBuilder[B] - b ++= thisCC - b ++= that - b.result - } - - /** Create a new iterable of type CC which contains all elements of this iterable - * followed by all elements of Iterator `that' - */ - def ++[B >: A](that: Iterator[B]): CC[B] = { - val b = newBuilder[B] - b ++= thisCC - b ++= that - b.result - } - - /** Returns the iterable resulting from applying the given function - * <code>f</code> to each element of this iterable. - * - * @param f function to apply to each element. - * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> if this - * iterable is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. - */ - def map[B](f: A => B): CC[B] = { - val b = newBuilder[B] - for (x <- this) b += f(x) - b.result - } - - /** Applies the given function <code>f</code> to each element of - * this iterable, then concatenates the results. - * - * @param f the function to apply on each element. - * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if - * this iterable is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. - */ - def flatMap[B](f: A => Iterable[B]): CC[B] = { - val b = newBuilder[B] - for (x <- this) b ++= f(x) - b.result - } - - /** Returns all the elements of this iterable that satisfy the - * predicate <code>p</code>. The order of the elements is preserved. - * @param p the predicate used to filter the iterable. - * @return the elements of this iterable satisfying <code>p</code>. - */ - def filter(p: A => Boolean): CC[A] = { - val b = newBuilder[A] - for (x <- this) - if (p(x)) b += x - b.result - } - - /** Removes all elements of the iterable which satisfy the predicate - * <code>p</code>. This is like <code>filter</code> with the - * predicate inversed. - * - * @param p the predicate to use to test elements - * @return the iterable without all elements which satisfy <code>p</code> - */ - def remove(p: A => Boolean): CC[A] = filter(!p(_)) - - /** Partitions this iterable in two iterables according to a predicate. - * - * @param p the predicate on which to partition - * @return a pair of iterables: the iterable that satisfies the predicate - * <code>p</code> and the iterable that does not. - * The relative order of the elements in the resulting iterables - * is the same as in the original iterable. - */ - def partition(p: A => Boolean): (CC[A], CC[A]) = { - val l, r = newBuilder[A] - for (x <- this) (if (p(x)) l else r) += x - (l.result, r.result) - } - - /** Apply a function <code>f</code> to all elements of this - * iterable object. - * - * @note Will not terminate for infinite-sized collections. - * @param f a function that is applied to every element. - * Note this function underlies the implementation of most other bulk operations. - * It should be overridden in concrete collectionc classes with efficient implementations. - */ - def foreach(f: A => Unit): Unit = elements.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 - */ - def forall(p: A => Boolean): Boolean = { - var result = true - breakable { - for (x <- this) - if (!p(x)) { result = false; break } - } - result - } - - /** 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 - */ - def exists(p: A => Boolean): Boolean = { - var result = false - breakable { - for (x <- this) - if (p(x)) { result = true; break } - } - result - } - - /** Count the number of elements in the iterable which satisfy a predicate. - * - * @param p the predicate for which to count - * @return the number of elements satisfying the predicate <code>p</code>. - */ - def count(p: A => Boolean): Int = { - var cnt = 0 - for (x <- this) { - if (p(x)) cnt += 1 - } - cnt - } - - /** Find and return the first element of the iterable object satisfying a - * predicate, if any. - * - * @note may 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 p the predicate - * @return an option containing the first element in the iterable object - * satisfying <code>p</code>, or <code>None</code> if none exists. - */ - def find(p: A => Boolean): Option[A] = { - var result: Option[A] = None - breakable { - for (x <- this) - if (p(x)) { result = Some(x); break } - } - result - } - - /** Combines the elements of this iterable object together using the binary - * function <code>f</code>, from left to right, and starting with - * the value <code>z</code>. - * - * @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 <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...), - * a<sub>n</sub>)</code> if the iterable is - * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>. - */ - def foldLeft[B](z: B)(op: (B, A) => B): B = { - var result = z - for (x <- this) - result = op(result, x) - result - } - - /** Combines the elements of this iterable together using the binary - * function <code>f</code>, from right to left, and starting with - * the value <code>z</code>. - * - * @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 <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code> - * if the iterable is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>. - */ - def foldRight[B](z: B)(op: (A, B) => B): B = elements.foldRight(z)(op) - - /** Similar to <code>foldLeft</code> but can be used as - * an operator with the order of iterable and zero arguments reversed. - * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code> - * @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. - */ - def /: [B](z: B)(op: (B, A) => B): B = foldLeft(z)(op) - - /** An alias for <code>foldRight</code>. - * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code> - * @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. - */ - def :\ [B](z: B)(op: (A, B) => B): B = foldRight(z)(op) - - /** Combines the elements of this iterable object together using the binary - * operator <code>op</code>, from left to right - * @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 - * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code> - if the iterable object has elements - * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>. - * @throws Predef.UnsupportedOperationException if the iterable object is empty. - */ - def reduceLeft[B >: A](op: (B, A) => B): B = { - if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft") - var result: B = elements.next - var first = true - for (x <- this) - if (first) first = false - else result = op(result, x) - result - } - - /** Combines the elements of this iterable object together using the binary - * operator <code>op</code>, 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 - * - * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code> - * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., - * a<sub>n</sub></code>. - * - * @throws Predef.UnsupportedOperationException if the iterator is empty. - */ - def reduceRight[B >: A](op: (A, B) => B): B = - elements.reduceRight(op) - - /** Returns an iterable formed from this iterable and the specified iterable - * `other` by associating each element of the former with - * the element at the same position in the latter. - * If one of the two iterables is longer than the other, its remaining elements are ignored. - */ - def zip[B](that: Iterable[B]): CC[(A, B)] = { - val these = this.elements - val those = that.elements - val b = this.newBuilder[(A, B)] - while (these.hasNext && those.hasNext) - b += ((these.next, those.next)) - b.result - } - - /** Returns a iterable formed from this iterable and the specified iterable - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * - * @param that iterable <code>that</code> may have a different length - * as the self iterable. - * @param thisElem element <code>thisElem</code> is used to fill up the - * resulting iterable if the self iterable is shorter than - * <code>that</code> -b * @param thatElem element <code>thatElem</code> is used to fill up the - * resulting iterable if <code>that</code> is shorter than - * the self iterable - * @return <code>Iterable((a<sub>0</sub>,b<sub>0</sub>), ..., - * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>), - * ..., {elem,b<sub>m</sub>})</code> - * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip - * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is - * invoked where <code>m > n</code>. - */ - def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): CC[(A1, B1)] = { - val these = this.elements - val those = that.elements - val b = newBuilder[(A1, B1)] - while (these.hasNext && those.hasNext) - b += ((these.next, those.next)) - while (these.hasNext) - b += ((these.next, thatElem)) - while (those.hasNext) - b += ((thisElem, those.next)) - b.result - } - - /** Zips this iterable with its indices. `s.zipWithIndex` is equivalent to - * `s zip s.indices`, but is usually more efficient. - */ - def zipWithIndex: CC[(A, Int)] = { - val b = newBuilder[(A, Int)] - var i = 0 - for (x <- this) { - b += ((x, i)) - i +=1 - } - b.result - } - - /** Copy all elements to a given buffer - * @note Will not terminate for infinite-sized collections. - * @param dest The buffer to which elements are copied - */ - def copyToBuffer[B >: A](dest: Buffer[B]) { - for (x <- this) dest += x - } - - /** Fills the given array <code>xs</code> with at most `len` elements of - * this iterable starting at position `start`. - * Copying will stop oce either the end of the current iterable is reached or - * `len` elements have been copied. - * - * @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 - * @pre the array must be large enough to hold all elements. - */ - def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) { - var i = start - val end = (start + len) min xs.length - for (x <- this) { - if (i < end) { - xs(i) = x - i += 1 - } - } - } - - /** Fills the given array <code>xs</code> with the elements of - * this iterable starting at position <code>start</code> - * until either the end of the current iterable or the end of array `xs` is reached. - * - * @note Will not terminate for infinite-sized collections. - * @param xs the array to fill. - * @param start starting index. - * @pre the array must be large enough to hold all elements. - */ - def copyToArray[B >: A](xs: Array[B], start: Int) { - copyToArray(xs, start, xs.length - start) - } - - /** Converts this collection to a fresh Array elements. - * @note Will not terminate for infinite-sized collections. - */ - def toArray[B >: A]: Array[B] = { - var size = 0 - for (x <- this) size += 1 - val result = new Array[B](size) - copyToArray(result, 0) - result - } - - /** - * Create a fresh list with all the elements of this iterable object. - * @note Will not terminate for infinite-sized collections. - */ - def toList: List[A] = (new ListBuffer[A] ++ thisCC).toList - - /** - * Returns a sequence containing all of the elements in this iterable object. - * @note Will not terminate for infinite-sized collections. - */ - def toSequence: Sequence[A] = toList - - /** @deprecated use toSequence instead - */ - @deprecated def toSeq: Sequence[A] = toSequence - - /** - * Create a stream which contains all the elements of this iterable object. - * @note consider using <code>projection</code> for lazy behavior. - */ - def toStream: Stream[A] = elements.toStream - - /** Sort the iterable according to the comparison function - * <code><(e1: a, e2: a) => Boolean</code>, - * which should be true iff <code>e1</code> is smaller than - * <code>e2</code>. - * The sort is stable. That is elements that are equal wrt `lt` appear in the - * same order in the sorted iterable as in the original. - * - * @param lt the comparison function - * @return a iterable sorted according to the comparison function - * <code><(e1: a, e2: a) => Boolean</code>. - * @ex <pre> - * List("Steve", "Tom", "John", "Bob") - * .sort((e1, e2) => (e1 compareTo e2) < 0) = - * List("Bob", "John", "Steve", "Tom")</pre> - * !!! - def sortWith(lt : (A,A) => Boolean): CC[A] = { - val arr = toArray - Array.sortWith(arr, lt) - val b = newBuilder[A] - for (x <- arr) b += x - b.result - } - */ - - /** Returns a string representation of this iterable object. The resulting string - * begins with the string <code>start</code> and is finished by the string - * <code>end</code>. Inside, the string representations of elements (w.r.t. - * the method <code>toString()</code>) are separated by the string - * <code>sep</code>. - * - * @ex <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code> - * @param start starting string. - * @param sep separator string. - * @param end ending string. - * @return a string representation of this iterable object. - */ - def mkString(start: String, sep: String, end: String): String = - addString(new StringBuilder(), start, sep, end).toString - - /** Returns a string representation of this iterable object. The string - * representations of elements (w.r.t. the method <code>toString()</code>) - * are separated by the string <code>sep</code>. - * - * @param sep separator string. - * @return a string representation of this iterable object. - */ - def mkString(sep: String): String = - addString(new StringBuilder(), sep).toString - - /** Converts a collection into a flat <code>String</code> by each element's toString method. - */ - def mkString = - addString(new StringBuilder()).toString - - /** Write all elements of this iterable into given string builder. - * The written text begins with the string <code>start</code> and is finished by the string - * <code>end</code>. Inside, the string representations of elements (w.r.t. - * the method <code>toString()</code>) are separated by the string - * <code>sep</code>. - */ - def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = { - b append start - var first = true - for (x <- this) { - if (first) first = false - else b append sep - b append x - } - b append end - } - - /** Write all elements of this string into given string builder. - * The string representations of elements (w.r.t. the method <code>toString()</code>) - * are separated by the string <code>sep</code>. - */ - def addString(b: StringBuilder, sep: String): StringBuilder = addString(b, "", sep, "") - - /** Write all elements of this string into given string builder without using - * any separator between consecutive elements. - */ - def addString(b: StringBuilder): StringBuilder = addString(b, "") - - /** - * returns a projection that can be used to call non-strict <code>filter</code>, - * <code>map</code>, and <code>flatMap</code> methods that build projections - * of the collection. - def projection : Iterable.Projection[A] = new Iterable.Projection[A] { - def elements = Iterable.this.elements - override def force = Iterable.this - } - */ - - override def toString = mkString(stringPrefix + "(", ", ", ")") - - /** Defines the prefix of this object's <code>toString</code> representation. - */ - def stringPrefix : String = { - var string = this.getClass.getName - val idx1 = string.lastIndexOf('.' : Int) - if (idx1 != -1) string = string.substring(idx1 + 1) - val idx2 = string.indexOf('$') - if (idx2 != -1) string = string.substring(0, idx2) - string - } - - /** Creates a view of this iterable @see IterableView - */ - def view: IterableView[CC, A] = new IterableView[CC, A] { // !!! Martin: We should maybe infer the type parameters here? - val origin = thisCC - val elements: Iterator[A] = self.elements - } - -// The following methods return non-deterministic results, unless this iterable is an OrderedIterable - - /** The first element of this iterable. - * - * @note Might return different results for different runs, unless this iterable is ordered - * @throws Predef.NoSuchElementException if the iterable is empty. - */ - def head: A = if (isEmpty) throw new NoSuchElementException else elements.next - - /** @deprecated use head instead */ - @deprecated def first: A = head - - /** Returns as an option the first element of this iterable - * or <code>None</code> if iterable is empty. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def headOption: Option[A] = if (isEmpty) None else Some(head) - - /** @deprecated use headOption instead - * <code>None</code> if iterable is empty. - */ - @deprecated def firstOption: Option[A] = headOption - - /** An iterable consisting of all elements of this iterable - * except the first one. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def tail: CC[A] = drop(1) - - /** Return an iterable consisting only of the first <code>n</code> - * elements of this iterable, or else the whole iterable, if it has less - * than <code>n</code> elements. - * - * @param n the number of elements to take - * @note Might return different results for different runs, unless this iterable is ordered - */ - def take(n: Int): CC[A] = { - val b = newBuilder[A] - var i = 0 - breakable { - for (x <- this) { - b += x - i += 1 - if (i == n) break - } - } - b.result - } - - /** Returns this iterable without its <code>n</code> first elements - * If this iterable has less than <code>n</code> elements, the empty - * iterable is returned. - * - * @param n the number of elements to drop - * @return the new iterable - * @note Might return different results for different runs, unless this iterable is ordered - */ - def drop(n: Int): CC[A] = { - val b = newBuilder[A] - var i = 0 - for (x <- this) { - if (i >= n) b += x - i += 1 - } - 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 - * @throws IndexOutOfBoundsException if <code>from < 0</code> - * or <code>length < from + len<code> - * @note Might return different results for different runs, unless this iterable is ordered - */ - def slice(from: Int, until: Int): CC[A] = { - val b = newBuilder[A] - var i = 0 - breakable { - for (x <- this) { - if (i >= from) b += x - i += 1 - if (i == until) break - } - } - b.result - } - - /** Split the iterable at a given point and return the two parts thus - * created. - * - * @param n the position at which to split - * @return a pair of iterables composed of the first <code>n</code> - * elements, and the other elements. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def splitAt(n: Int): (CC[A], CC[A]) = { - val l, r = newBuilder[A] - var i = 0 - for (x <- this) - (if (i < n) l else r) += x - (l.result, r.result) - } - - /** 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) - */ - def view(from: Int, until: Int): IterableView[CC, A] = view.slice(from, until) -} diff --git a/src/library/scalax/collection/generic/covartest/IterableView.scala b/src/library/scalax/collection/generic/covartest/IterableView.scala deleted file mode 100755 index 43a1f68dc0..0000000000 --- a/src/library/scalax/collection/generic/covartest/IterableView.scala +++ /dev/null @@ -1,112 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - -package scalax.collection.generic.covartest - -/** A non-strict projection of an iterable. - * @author Sean McDirmid - * @author Martin Odersky - * @note this should really be a virtual class of SequenceFactory - */ -trait IterableView[+UC[+B] <: Iterable[B], +A] extends Iterable[A] { self => - - val origin: Iterable[_] - def elements: Iterator[A] - - val underlying: Iterable[_] = origin match { - case v: IterableView[t, _] => v.underlying - case _ => origin - } - - protected def isDelay = elements eq underlying.elements - - private[this] var forced: UC[A] = _ - private[this] var wasForced = false - - def force: UC[A] = { - if (!wasForced) { - forced = { - val b = underlying.newBuilder[A] - for (x <- elements) - b += x - b.result - }.asInstanceOf[UC[A]] - wasForced = true - } - forced - } - - def newBuilder[A] = underlying.newBuilder[A] - - /** Builds a new view object. This method needs to be overridden in subclasses - * which refine in IterableView type - */ - protected def newView[B](elems: Iterator[B]) = new IterableView[UC, B] { - val origin = if (self.isDelay) self.origin else self - val elements = elems - } - - /** Non-strict variant of @see IterableLike.++ */ - override def ++[B >: A](that: Iterator[B]): IterableView[UC, B] = newView(elements ++ that) - - /** Non-strict variant of @see IterableLike.++ */ - override def ++[B >: A](that: Iterable[B]): IterableView[UC, B] = newView(elements ++ that.elements) - - /** Non-strict variant of @see IterableLike.map */ - override def map[B](f: A => B): IterableView[UC, B] = newView(elements map f) - - /** Non-strict variant of @see IterableLike.flatMap */ - override def flatMap[B](f: A => Iterable[B]): IterableView[UC, B] = newView(elements flatMap (f(_).elements)) - - /** Non-strict variant of @see IterableLike.filter */ - override def filter(p: A => Boolean): IterableView[UC, A] = newView(elements filter p) - - /** Non-strict variant of @see IterableLike.partition */ - override def partition(p: A => Boolean): (IterableView[UC, A], IterableView[UC, A]) = { - val (li, ri) = elements partition p - (newView(li), newView(ri)) - } - - /** Non-strict variant of @see IterableLike.zip */ - override def zip[B](other: Iterable[B]): IterableView[UC, (A, B)] = newView(elements zip other.elements) - - /** Non-strict variant of @see IterableLike.zipWithIndex */ - override def zipWithIndex: IterableView[UC, (A, Int)] = newView(elements.zipWithIndex) - - /* Non-strict variant of @see IterableLike.zipAll - * This is not enabled because it can't be specialized in VectorView: - * VectorView is not covariant, yet must maintain updatability. Impossible to do this - * with this type signature. - override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): IterableView[UC, (A1, B1)] = - newView(elements zipAll (that.elements, thisElem, thatElem)) - */ - - /** Non-strict variant of @see Iterable.take */ - override def take(n: Int): IterableView[UC, A] = newView(elements take n) - - /** Non-strict variant of @see Iterable.drop */ - override def drop(n: Int): IterableView[UC, A] = newView(elements drop n) - - /** Non-strict variant of @see Iterable.splitAt */ - override def splitAt(n: Int): (IterableView[UC, A], IterableView[UC, A]) = (take(n), drop(n)) - - /** Non-strict variant of @see Iterable.slice */ - override def slice(from: Int, until: Int): IterableView[UC, A] = newView(elements slice (from, until)) - - /** The projection resulting from the concatenation of this projection with the <code>rest</code> projection. - * @param rest The projection that gets appended to this projection - * @deprecated Use ++ instead - */ - @deprecated def append[B >: A](rest : => Iterable[B]): IterableView[UC, B] = this ++ rest.elements - - override def stringPrefix = origin.stringPrefix+"V" - - -} diff --git a/src/library/scalax/collection/generic/covartest/OrderedIterableForwarder.scala b/src/library/scalax/collection/generic/covartest/OrderedIterableForwarder.scala deleted file mode 100755 index 3a33dc6694..0000000000 --- a/src/library/scalax/collection/generic/covartest/OrderedIterableForwarder.scala +++ /dev/null @@ -1,37 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ - - -package scalax.collection.generic.covartest - -/** This trait implements a forwarder for iterable objects. It forwards - * all calls to a different iterable object, except for - * - * - toString, hashCode, equals, stringPrefix - * - newBuilder, view - * - all calls creating a new iterable object of the same kind - * - * The above methods are forwarded by subclass IterableProxy - * - * @author Martin Odersky - * @version 2.8 - */ -trait OrderedIterableForwarder[+A] extends OrderedIterable[A] with IterableForwarder[A] { - - /** The iterable object to which calls are forwarded */ - protected def underlying: OrderedIterable[A] - - // Iterable delegates - // Iterable methods could be printed by cat IterableTemplate.scala | sed -n '/trait Iterable/,$ p' | egrep '^ (override )?def' - - override def last: A = underlying.last - override def lastOption: Option[A] = underlying.lastOption - override def sameElements[B >: A](that: OrderedIterable[B]): Boolean = underlying.sameElements(that) -} diff --git a/src/library/scalax/collection/generic/covartest/OrderedIterableTemplate.scala b/src/library/scalax/collection/generic/covartest/OrderedIterableTemplate.scala deleted file mode 100755 index f3c509887c..0000000000 --- a/src/library/scalax/collection/generic/covartest/OrderedIterableTemplate.scala +++ /dev/null @@ -1,161 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - - -package scalax.collection.generic.covartest - -import OrderedIterable._ - -import util.control.Breaks._ - -/** Ordered iterables are iterables where the `elements` method always returns elements in the same - * order (namely the order in which elements were appended to the iterable). In particular, one has - * for every two ordered iterables `xs` and `ys`: - * - * `(xs ++ ys).elements = xs.elements ++ ys.elements - */ -trait OrderedIterableTemplate[+CC[+B] <: OrderedIterableTemplate[CC, B] with OrderedIterable[B], +A] - extends IterableTemplate[CC, A] { - - /** The last element of this iterable. - * - * @throws Predef.NoSuchElementException if the iterable is empty. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def last: A = { - var lst = head - for (x <- this) - lst = x - lst - } - - /** Returns as an option the last element of this iterable or - * <code>None</code> if iterable is empty. - * - * @return the last element as an option. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def lastOption: Option[A] = if (isEmpty) None else Some(last) - - /** An iterable consisting of all elements of this iterable except the last one. - * @throws Predef.UnsupportedOperationException if the stream is empty. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def init: CC[A] = { - if (isEmpty) throw new UnsupportedOperationException("empty.init") - var lst = head - val b = newBuilder[A] - for (x <- this) { - b += lst - lst = x - } - b.result - } - - /** Returns the rightmost <code>n</code> elements from this iterable. - * - * @param n the number of elements to take - * @note Might return different results for different runs, unless this iterable is ordered - */ - def takeRight(n: Int): CC[A] = { - val b = newBuilder[A] - val lead = elements drop n - var go = false - for (x <- this) { - if (go) b += x - else if (lead.hasNext) lead.next - else go = true - } - b.result - } - - /** Returns the iterable wihtout its rightmost <code>n</code> elements. - * - * @param n the number of elements to take - * @note Might return different results for different runs, unless this iterable is ordered - */ - def dropRight(n: Int): CC[A] = { - val b = newBuilder[A] - val lead = elements drop n - breakable { - for (x <- this) { - if (!lead.hasNext) break - lead.next - b += x - } - } - b.result - } - - /** Returns the longest prefix of this iterable whose elements satisfy - * the predicate <code>p</code>. - * - * @param p the test predicate. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def takeWhile(p: A => Boolean): CC[A] = { - val b = newBuilder[A] - breakable { - for (x <- this) { - if (!p(x)) break - b += x - } - } - b.result - } - - /** Returns the longest suffix of this iterable whose first element - * does not satisfy the predicate <code>p</code>. - * - * @param p the test predicate. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def dropWhile(p: A => Boolean): CC[A] = { - val b = newBuilder[A] - var go = false - for (x <- this) { - if (go) b += x - else if (!p(x)) { go = true; b += x } - } - b.result - } - - /** Returns a pair consisting of the longest prefix of the iterable whose - * elements all satisfy the given predicate, and the rest of the iterable. - * - * @param p the test predicate - * @return a pair consisting of the longest prefix of the iterable whose - * elements all satisfy <code>p</code>, and the rest of the iterable. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def span(p: A => Boolean): (CC[A], CC[A]) = { - val l, r = newBuilder[A] - var toLeft = true - for (x <- this) { - toLeft = toLeft && p(x) - (if (toLeft) l else r) += x - } - (l.result, r.result) - } - - /** Checks if the other iterable object contains the same elements as this one. - * - * @note will not terminate for infinite-sized iterables. - * @param that the other iterable - * @return true, iff both iterables contain the same elements. - * @note Might return different results for different runs, unless this iterable is ordered - */ - def sameElements[B >: A](that: OrderedIterable[B]): Boolean = { - val these = this.elements - val those = that.elements - while (these.hasNext && those.hasNext && these.next() == those.next()) {} - !these.hasNext && !those.hasNext - } -} diff --git a/src/library/scalax/collection/generic/covartest/SequenceFactory.scala b/src/library/scalax/collection/generic/covartest/SequenceFactory.scala deleted file mode 100755 index eb6c093bff..0000000000 --- a/src/library/scalax/collection/generic/covartest/SequenceFactory.scala +++ /dev/null @@ -1,11 +0,0 @@ -package scalax.collection.generic.covartest - -trait SequenceFactory[CC[A] <: Sequence[A]] extends IterableFactory[CC] { - - /** This method is called in a pattern match { case Sequence(...) => }. - * - * @param x the selector value - * @return sequence wrapped in an option, if this is a Sequence, otherwise none - */ - def unapplySeq[A](x: CC[A]): Some[CC[A]] = Some(x) -} diff --git a/src/library/scalax/collection/generic/covartest/SequenceForwarder.scala b/src/library/scalax/collection/generic/covartest/SequenceForwarder.scala deleted file mode 100644 index 47c512545d..0000000000 --- a/src/library/scalax/collection/generic/covartest/SequenceForwarder.scala +++ /dev/null @@ -1,50 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: SeqProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $ - - -package scalax.collection.generic.covartest - -/** This class implements a forwarder for sequences. It forwards - * all calls to a different sequence object except for - * - * - toString, hashCode, equals, stringPrefix - * - newBuilder, view, toSequence - * - all calls creating a new iterable objetc of the same kind - * - * The above methods are forwarded by subclass SequenceProxy - * - * @author Martin Odersky - * @version 2.8 - */ -trait SequenceForwarder[+A] extends Sequence[A] with OrderedIterableForwarder[A] { - - protected override def underlying: Sequence[A] - - // PartialFunction delegates - - override def apply(i: Int): A = underlying.apply(i) - override def isDefinedAt(x: Int): Boolean = underlying.isDefinedAt(x) - - // Sequence delegates - // Sequence methods could be printed by cat SequenceTemplate.scala | sed -n '/trait Seq/,$ p' | egrep '^ (override )?def' - - override def length: Int = underlying.length - override def lengthCompare(l: Int) = underlying lengthCompare l - override def segmentLength(p: A => Boolean, from: Int): Int = underlying.segmentLength(p, from) - override def prefixLength(p: A => Boolean) = underlying.prefixLength(p) - override def indexWhere(p: A => Boolean, from: Int): Int = underlying.indexWhere(p, from) - override def indexOf[B >: A](elem: B, from: Int): Int = underlying.indexOf(elem, from) - override def reversedElements: Iterator[A] = underlying.reversedElements - override def startsWith[B](that: Sequence[B], offset: Int): Boolean = underlying.startsWith(that, offset) - override def endsWith[B](that: Sequence[B]): Boolean = underlying.endsWith(that) - override def indexOf[B >: A](that: Sequence[B]): Int = underlying.indexOf(that) - override def contains(elem: Any): Boolean = underlying.contains(elem) - override def indices: Range = underlying.indices -} diff --git a/src/library/scalax/collection/generic/covartest/SequenceTemplate.scala b/src/library/scalax/collection/generic/covartest/SequenceTemplate.scala deleted file mode 100755 index eab7904af8..0000000000 --- a/src/library/scalax/collection/generic/covartest/SequenceTemplate.scala +++ /dev/null @@ -1,382 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ - - -package scalax.collection.generic.covartest - -import util.control.Breaks._ -import scalax.collection.immutable.{List, Nil, ::} - -import Sequence._ - -trait SequenceTemplate[+CC[+B] <: SequenceTemplate[CC, B] with Sequence[B], +A] extends PartialFunction[Int, A] with OrderedIterableTemplate[CC, A] { -self /*: CC[A]*/ => - - /** Returns the length of the sequence. - * - * @return the sequence length. - */ - def length: Int - - /** Result of comparing <code>length</code> with operand <code>len</code>. - * returns <code>x</code> where - * <code>x < 0</code> iff <code>this.length < len</code> - * <code>x == 0</code> iff <code>this.length == len</code> - * <code>x > 0</code> iff <code>this.length > len</code>. - * - * 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 - breakable { - for (_ <- this) { - i += 1 - if (i > len) break - } - } - i - len - } - - /** Should always be <code>length</code> */ - def size = length - - /** Is this partial function defined for the index <code>x</code>? - */ - def isDefinedAt(x: Int): Boolean = (x >= 0) && (x < length) - - /** Returns index of the first element satisying a predicate, or -1, if none exists. - * - * @note may not terminate for infinite-sized collections. - * @param p the predicate - */ - def indexWhere(p: A => Boolean): Int = indexWhere(p, 0) - - /** 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 - */ - def segmentLength(p: A => Boolean, from: Int): Int = { - var result = 0 - var i = from - breakable { - for (x <- this) { - if (i >= from && !p(x)) { result = i - from; break } - else i += 1 - } - } - result - } - - /** 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 - */ - def prefixLength(p: A => Boolean) = segmentLength(p, 0) - - /** Returns index of the first element starting from a start index - * satisying a predicate, or -1, if none exists. - * - * @note may not terminate for infinite-sized collections. - * @param p the predicate - * @param from the start index - */ - def indexWhere(p: A => Boolean, from: Int): Int = { - var result = -1 - var i = from - breakable { - for (x <- this) { - if (i >= from && p(x)) { result = i; break } - else i += 1 - } - } - result - } - - /** Returns index of the first element satisying a predicate, or -1. - * - * @deprecated Use `indexWhere` instead - */ - @deprecated def findIndexOf(p: A => Boolean): Int = indexWhere(p) - - /** Returns the index of the first occurence of the specified - * object in this iterable object. - * - * @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. - */ - def indexOf[B >: A](elem: B): Int = indexOf(elem, 0) - - /** Returns the index of the first occurence of the specified - * object in this iterable object, starting from a start index, or - * -1, if none exists. - * - * @note may not terminate for infinite-sized collections. - * @param elem element to search for. - */ - 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. - * - * @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. - */ - def lastIndexOf[B >: A](elem: B): Int = lastIndexOf(elem, length - 1) - - /** 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 - */ - def lastIndexOf[B >: A](elem: B, end: Int): Int = { - var i = end - val it = reversedElements - while (it.hasNext && it.next != elem) i -= 1 - i - } - - /** Returns index of the last element satisying a predicate, or -1, if none exists. - * - * @param p the predicate - * @return the index of the last element satisfying <code>p</code>, - * or -1 if such an element does not exist - */ - 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. - * - * @param end the end index - * @param p the predicate - */ - def lastIndexWhere(p: A => Boolean, end: Int): Int = { - var i = end - val it = reversedElements - while (it.hasNext && (i > end || !p(it.next))) i -= 1 - i - } - - /** A sequence of type <code>C</code> consisting of all elements of - * this sequence in reverse order. - * @note the operation is implemented by building a new sequence - * from <code>this(length - 1), ..., this(0)</code> - * If random access is inefficient for the given sequence implementation, - * this operation should be overridden. - */ - def reverse: CC[A] = { - var xs: List[A] = List() - for (x <- this) - xs = x :: xs - val b = newBuilder[A] - for (x <- xs) - b += x - b.result - } - - /** The elements of this sequence in reversed order - */ - def reversedElements: Iterator[A] = reverse.elements - - /** - * Checks whether the argument sequence is contained at the - * specified index within the receiver object. - * - * If the both the receiver object, <code>this</code> and - * the argument, <code>that</code> are infinite sequences - * this method may not terminate. - * - * @return true if <code>that</code> is contained in - * <code>this</code>, at the specified index, otherwise false - * - * @see String.startsWith - */ - def startsWith[B](that: Sequence[B], offset: Int): Boolean = { - val i = elements.drop(offset) - val j = that.elements - while (j.hasNext && i.hasNext && i.next == j.next) {} - !j.hasNext - } - - /** - * Check whether the receiver object starts with the argument sequence. - * - * @return true if <code>that</code> is a prefix of <code>this</code>, - * otherwise false - * - * @see Sequence.startsWith - */ - def startsWith[B](that: Sequence[B]): Boolean = startsWith(that, 0) - - /** @return true if this sequence end with that sequence - * @see String.endsWith - */ - def endsWith[B](that: Sequence[B]): Boolean = { - val i = this.elements.drop(length - that.length) - val j = that.elements - while (i.hasNext && j.hasNext && i.next == j.next) () - !j.hasNext - } - - /** @return -1 if <code>that</code> not contained in this, otherwise the - * index where <code>that</code> is contained - * @see String.indexOf - */ - def indexOf[B >: A](that: Sequence[B]): Int = { - var i = 0 - var s: Sequence[A] = thisCC - while (!s.isEmpty && !(s startsWith that)) { - i += 1 - s = s drop 1 - } - if (!s.isEmpty || that.isEmpty) i else -1 - } - - /** Tests if the given value <code>elem</code> is a member of this - * sequence. - * - * @param elem element whose membership has to be tested. - * @return <code>true</code> iff there is an element of this sequence - * which is equal (w.r.t. <code>==</code>) to <code>elem</code>. - */ - def contains(elem: Any): Boolean = exists (_ == elem) - - /** Computes the union of this sequence and the given sequence - * <code>that</code>. - * - * @param that the sequence of elements to add to the sequence. - * @return an sequence containing the elements of this - * sequence and those of the given sequence <code>that</code> - * which are not contained in this sequence. - */ - def union[B >: A](that: Sequence[B]): CC[B] = this ++ (that diff thisCC) - - /** Computes the difference between this sequence and the given sequence - * <code>that</code>. - * - * @param that the sequence of elements to remove from this sequence. - * @return this sequence without the elements of the given sequence - * <code>that</code>. - */ - def diff[B >: A](that: Sequence[B]): CC[A] = this remove (that contains _) - - /** Computes the intersection between this sequence and the given sequence - * <code>that</code>. - * - * @param that the sequence to intersect. - * @return the sequence of elements contained both in this sequence and - * in the given sequence <code>that</code>. - */ - def intersect[B >: A](that: Sequence[B]): CC[A] = this filter(that contains _) - - /** Builds a new sequence from this sequence in which any duplicates (wrt to ==) removed. - * Among duplicate elements, only the first one is retained in the result sequence - */ - def removeDuplicates: CC[A] = { - val b = newBuilder[A] - var seen = Set[A]() - for (x <- this) { - if (!(seen contains x)) { - b += x - seen += x - } - } - b.result - } - - /** Returns a sequence of given length containing the elements of this sequence followed by zero - * or more occurrences of given elements. If this sequence is already at least as long as given - * length, it is returned directly. Otherwise, a new sequence is created consisting of the elements - * of this sequence followed by enough occurrences of the given elements to reach the given length. - */ - def padTo[B >: A](len: Int, elem: B): CC[B] = { - var diff = len - length - val b = newBuilder[B] //!!! drop [B] and get surprising results! - b ++= thisCC - while (diff > 0) { - b += elem - diff -=1 - } - b.result - } - - /** - * Overridden for efficiency. - * - * @return the sequence itself - */ - override def toSequence: Sequence[A] = thisCC - - def indices: Range = 0 until length - - /** Creates a view of this iterable @see OrderedIterable.View - */ - override def view: SequenceView[CC, A] = new SequenceView[CC, A] { // !!! Martin: We should maybe infer the type parameters here? - val origin: Sequence[_] = thisCC - val elements: Iterator[A] = self.elements - val length: Int = self.length - def apply(idx: Int): A = self.apply(idx) - } - - /** A sub-sequence 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 sequence, whereas `slice` produces a new sequence. - * - * @note view(from, to) is equivalent to view.slice(from, to) - */ - override def view(from: Int, until: Int): SequenceView[CC, A] = view.slice(from, until) - - /** Returns index of the last element satisying a predicate, or -1. - * @deprecated use `lastIndexWhere` instead - */ - @deprecated def findLastIndexOf(p: A => Boolean): Int = lastIndexWhere(p) - - /** A sub-sequence starting at index <code>from</code> - * and extending up to the length of the current sequence - * - * @param from The index of the first element of the slice - * @throws IndexOutOfBoundsException if <code>from < 0</code> - * @deprecated use <code>drop</code> instead - */ - @deprecated def slice(from: Int): Sequence[A] = slice(from, length) - - /** @deprecated Should be replaced by - * - * <code>(s1, s2) forall { case (x, y) => f(x, y) }</code> - */ - @deprecated def equalsWith[B](that: Sequence[B])(f: (A,B) => Boolean): Boolean = { - val i = this.elements - val j = that.elements - while (i.hasNext && j.hasNext && f(i.next, j.next)) () - !i.hasNext && !j.hasNext - } - - /** Is <code>that</code> a slice in this? - * @deprecated Should be repaced by <code>indexOf(that) != -1</code> - */ - @deprecated def containsSlice[B](that: Sequence[B]): Boolean = indexOf(that) != -1 - -} diff --git a/src/library/scalax/collection/generic/covartest/SequenceView.scala b/src/library/scalax/collection/generic/covartest/SequenceView.scala deleted file mode 100755 index e99ffaf652..0000000000 --- a/src/library/scalax/collection/generic/covartest/SequenceView.scala +++ /dev/null @@ -1,131 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ - - -package scalax.collection.generic.covartest - -import util.control.Breaks._ -import annotation.unchecked.uncheckedVariance - -import Sequence._ - -/** A non-strict projection of an iterable. - * @author Sean McDirmid - * @author Martin Odersky - * @note this should really be a virtual class of SequenceFactory - */ -trait SequenceView[+UC[+B] <: Sequence[B], +A] extends IterableView[UC, A] with Sequence[A] { -self => - - /** refined from Iterable.View */ - val origin: Sequence[_] - - override def newBuilder[A] = underlying.newBuilder[A].asInstanceOf[Builder[Sequence, A]] - - trait Transformed[+B] extends SequenceView[UC, B] { - val origin = self - protected def asCC = asInstanceOf[SequenceView[UC, B]] - } - - class Appended[+B >: A](that: Sequence[B]) extends Transformed[B] { - override def elements: Iterator[B] = self.elements ++ that.elements - override def length: Int = self.length + that.length - override def apply(idx: Int): B = { - val ll = self.length - if (idx < ll) self.apply(idx) else that.apply(idx - ll) - } - override def stringPrefix = self.stringPrefix + "A" - } - - class Sliced(from: Int, to: Int) extends Transformed[A] { - override def elements: Iterator[A] = self.elements slice (from, to) - override lazy val length: Int = ((to min self.length) - (from max 0) min 0) - override def apply(idx: Int): A = - if (idx >= 0 && idx < length) self.apply(idx + from) - else throw new IndexOutOfBoundsException(idx.toString) - override def stringPrefix = self.stringPrefix + "S" - override def slice(from1: Int, to1: Int) = - new self.Sliced(from + (from1 min length max 0) , to + (to1 min length max 0)).asInstanceOf[SequenceView[UC, A]] - } - - class Mapped[+B](f: A => B) extends Transformed[B] { - override def elements: Iterator[B] = self.elements map f - override def length: Int = self.length - override def apply(idx: Int): B = f(self.apply(idx)) - override def stringPrefix = self.stringPrefix + "M" - } - - class Reversed extends Transformed[A] { - override def elements: Iterator[A] = self.reversedElements - override def length: Int = self.length - override def apply(idx: Int): A = self.apply(length - 1 - idx) - override def stringPrefix = super.stringPrefix+"R" - } - - class Patched[+B >: A](from: Int, patch: Sequence[B], replaced: Int) extends Transformed[B] { - val plen = patch.length - override def elements: Iterator[B] = self.elements patch (from, patch, replaced) - override def length: Int = self.length + plen - replaced - override def apply(idx: Int): B = - if (idx < from) self.apply(idx) - else if (idx < from + plen) patch.apply(idx - from) - else self.apply(idx - plen + replaced) - override def stringPrefix = super.stringPrefix+"P" - } - - class Zipped[+B](that: Sequence[B]) extends Transformed[(A, B)] { - override def elements: Iterator[(A, B)] = self.elements zip that.elements - override def length = self.length min that.length - override def apply(idx: Int): (A, B) = (self.apply(idx), that.apply(idx)) - override def stringPrefix = super.stringPrefix+"Z" - } - - override def ++[B >: A](that: Iterable[B]): SequenceView[UC, B] = - new Appended[B](that.toSequence).asCC - override def ++[B >: A](that: Iterator[B]): SequenceView[UC, B] = - new Appended[B](that.toSequence).asCC - override def map[B](f: A => B): SequenceView[UC, B] = - new Mapped(f).asCC - override def reverse: SequenceView[UC, A] = - (new Reversed).asCC - def patch[B >: A](from: Int, patch: Sequence[B], replaced: Int): SequenceView[UC, B] = - if (0 <= from && from < length) new Patched(from, patch, replaced).asCC - else throw new IndexOutOfBoundsException(from.toString) - override def padTo[B >: A](len: Int, elem: B): SequenceView[UC, B] = - patch(length, fill((len - length) max 0)(elem), 0) - override def zip[B](that: Iterable[B]): SequenceView[UC, (A, B)] = - new Zipped(that.toSequence).asCC - override def zipWithIndex: SequenceView[UC, (A, Int)] = - zip((0 until length).asInstanceOf[Null]) // !@! - /* - override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): SequenceView[UC, (A1, B1)] = { - val that1 = that.toSequence - self.padTo(that1.length, thisElem) zip that1.padTo(this.length, thatElem)//.asInstanceOf[SequenceView[UC, (A1, B1)]] - }*/ - override def take(n: Int): SequenceView[UC, A] = - slice(0, n) - override def drop(n: Int): SequenceView[UC, A] = - slice(n, Math.MAX_INT) - override def splitAt(n: Int): (SequenceView[UC, A], SequenceView[UC, A]) = (take(n), drop(n)) - override def slice(from: Int, until: Int): SequenceView[UC, A] = - new Sliced(from, until).asCC - override def takeWhile(p: A => Boolean): SequenceView[UC, A] = - take(prefixLength(p)) - override def dropWhile(p: A => Boolean): SequenceView[UC, A] = - drop(prefixLength(p)) - override def span(p: A => Boolean): (SequenceView[UC, A], SequenceView[UC, A]) = { - val n = prefixLength(p) - (take(n), drop(n)) - } - - // missing here because we can't do anything about them, so we fall back to default construction - // if an IterableView via newView: flatMap, filter, partition -} - diff --git a/src/library/scalax/collection/immutable/DefaultSet.scala b/src/library/scalax/collection/immutable/DefaultSet.scala deleted file mode 100644 index a9ce3fb3df..0000000000 --- a/src/library/scalax/collection/immutable/DefaultSet.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: HashSet.scala 16884 2009-01-09 16:52:09Z cunei $ - -package scalax.collection.immutable - -import generic.SetTemplate - -/** A default implementation of immutable sets. - * This is currently implemented as a proxy for an immutable HashSet, - * except that its builder returns specialized representations EmptySet,Set1,..., Set4 - * for sets of size <= 4. - */ -class DefaultSet[A] private (hset: HashSet[A]) - extends Set[A] - with SetTemplate[Set, A] { - - def this() = this(new HashSet[A]) - - def contains(elem: A): Boolean = hset.contains(elem) - - def + (elem: A): Set[A] = hset + elem - - /** Keeps underlying HashSet representation, but switches back to EmptySet if - * result does not contain any elements - */ - def - (elem: A): Set[A] = { - val hset1 = hset - elem - if (hset1.isEmpty) new EmptySet[A] - else new DefaultSet(hset) - } - - def size: Int = hset.size - - def elements: Iterator[A] = hset.elements - - override def foreach(f: A => Unit): Unit = hset.foreach(f) -} - diff --git a/src/library/scalax/collection/immutable/EmptySet.scala b/src/library/scalax/collection/immutable/EmptySet.scala deleted file mode 100755 index 32c4915a49..0000000000 --- a/src/library/scalax/collection/immutable/EmptySet.scala +++ /dev/null @@ -1,38 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: EmptySet.scala 16893 2009-01-13 13:09:22Z cunei $ - - - -package scalax.collection.immutable - -import collection.generic.Builder - -/** This class implements empty immutable sets - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class EmptySet[A] extends Set[A] { - - def size: Int = 0 - - def contains(elem: A): Boolean = false - - def + (elem: A): Set[A] = new Set1(elem) - - def - (elem: A): Set[A] = this - - def elements: Iterator[A] = Iterator.empty - - override def foreach(f: A => Unit): Unit = {} -} - - - diff --git a/src/library/scalax/collection/immutable/HashMap.scala b/src/library/scalax/collection/immutable/HashMap.scala deleted file mode 100644 index 8aaa0239c1..0000000000 --- a/src/library/scalax/collection/immutable/HashMap.scala +++ /dev/null @@ -1,164 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: HashMap.scala 16893 2009-01-13 13:09:22Z cunei $ - - -package scalax.collection.immutable - -import generic._ - -/** The canonical factory methods for <a href="HashMap.html">immutable HashMap's</a>. - * - * @author Martin Odersky - * @version 2.0, 19/01/2007 - */ -object HashMap extends MapFactory[HashMap] { - - /** The empty map of this type */ - def empty[A, B] = new HashMap[A, B] - -} - -/** This class implements immutable maps using a hash table. - * It is optimized for sequential accesses where the last updated table is accessed most often. - * It supports with reasonable efficiency accesses to previous versions of the table by keeping - * a change log that's regularly compacted. - * It needs to synchronize most methods, so it is less suitable for highly concurrent accesses. - * - * @author Martin Odersky - * @version 2.0, 19/01/2007 - */ -@serializable -class HashMap[A, B] extends Map[A,B] - with MapTemplate[A, B, HashMap] - with collection.mutable.HashTable[A] { - - type Entry = collection.mutable.DefaultEntry[A, Any] - - protected var later: HashMap[A, B] = null - protected var oldKey: A = _ - protected var oldValue: Option[B] = _ - protected var deltaSize: Int = _ - - override def empty[B] = HashMap.empty[A, B] - - def get(key: A): Option[B] = synchronized { - var m = this - var cnt = 0 - while (m.later != null) { - if (key == m.oldKey) return m.oldValue - cnt += 1 - m = m.later - } - if (cnt > logLimit) makeCopy(m) - val e = m.findEntry(key) - if (e == null) None - else Some(getValue(e)) - } - - def update(key: A, value: B): HashMap[A, B] = synchronized { - makeCopyIfUpdated() - val e = findEntry(key) - if (e == null) { - markUpdated(key, None, 1) - later.addEntry(new Entry(key, value)) - } else { - markUpdated(key, Some(getValue(e)), 0) - e.value = value - } - later - } - - def - (key: A): HashMap[A, B] = synchronized { - makeCopyIfUpdated() - val e = findEntry(key) - if (e == null) this - else { - markUpdated(key, Some(getValue(e)), -1) - later removeEntry key - later - } - } - - override def size: Int = synchronized { - var m = this - var cnt = 0 - var s = 0 - while (m.later != null) { - s -= m.deltaSize - cnt += 1 - m = m.later - } - s += m.tableSize - if (cnt > logLimit) makeCopy(m) - s - } - - def elements = synchronized { - makeCopyIfUpdated() - entries map {e => (e.key, getValue(e))} - } - - private def getValue(e: Entry) = - e.value.asInstanceOf[B] - - private def logLimit: Int = Math.sqrt(table.length).toInt - - private def markUpdated(key: A, ov: Option[B], delta: Int) { - val lv = loadFactor - later = new HashMap[A, B] { - override def initialSize = 0 - override def loadFactor = lv - table = HashMap.this.table - tableSize = HashMap.this.tableSize - threshold = HashMap.this.threshold - } - oldKey = key - oldValue = ov - deltaSize = delta - } - - private def makeCopy(last: HashMap[A, B]) { - def undo(m: HashMap[A, B]) { - if (m ne last) { - undo(m.later) - if (m.deltaSize == 1) removeEntry(m.oldKey) - else if (m.deltaSize == 0) findEntry(m.oldKey).value = m.oldValue.get - else if (m.deltaSize == -1) addEntry(new Entry(m.oldKey, m.oldValue.get)) - } - } - def copy(e: Entry): Entry = - if (e == null) null - else { - val rest = copy(e.next) - val result = new Entry(e.key, e.value) - result.next = rest - result - } - val ltable = last.table - val s = ltable.length - table = new scala.Array[collection.mutable.HashEntry[A, Entry]](s) - var i = 0 - while (i < s) { - table(i) = copy(ltable(i).asInstanceOf[Entry]) - i += 1 - } - tableSize = last.tableSize - threshold = last.threshold - undo(this) - later = null - } - - private def makeCopyIfUpdated() { - var m = this - while (m.later != null) m = m.later - if (m ne this) makeCopy(m) - } -} - diff --git a/src/library/scalax/collection/immutable/HashSet.scala b/src/library/scalax/collection/immutable/HashSet.scala deleted file mode 100644 index 56394b9bc6..0000000000 --- a/src/library/scalax/collection/immutable/HashSet.scala +++ /dev/null @@ -1,138 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: HashSet.scala 16884 2009-01-09 16:52:09Z cunei $ - -package scalax.collection.immutable - -import generic.{SetTemplate, SetFactory, AddableBuilder} - -/** The canonical factory methods for <a href="HashSet.html">immutable HashSet's<la>. - * - * @author Martin Odersky - * @version 2.8 - */ -object HashSet extends SetFactory[HashSet] { - - /** The empty set of this type. - */ - def empty[A] = new HashSet[A] - -} - -/** This class implements immutable maps/sets using a hash table. - * It is optimized for sequential accesses where the last updated table is accessed most often. - * It supports with reasonable efficiency accesses to previous versions of the table by keeping - * a change log that's regularly compacted. - * It needs to synchronize most methods, so it is less suitable for highly concurrent accesses. - * - * @author Martin Odersky - * @version 2.0, 19/01/2007 - */ -@serializable -class HashSet[A] extends Set[A] - with SetTemplate[HashSet, A] - with mutable.FlatHashTable[A] { - protected var later: HashSet[A] = null - protected var changedElem: A = _ - protected var deleted: Boolean = _ - - def contains(elem: A): Boolean = synchronized { - var m = this - var cnt = 0 - while (m.later != null) { - if (elem == m.changedElem) return m.deleted - cnt += 1 - m = m.later - } - if (cnt > logLimit) makeCopy(m) - m.containsEntry(elem) - } - - def + (elem: A): HashSet[A] = synchronized { - makeCopyIfUpdated() - if (containsEntry(elem)) this - else { - markUpdated(elem, false) - later addEntry elem - later - } - } - - def - (elem: A): HashSet[A] = synchronized { - makeCopyIfUpdated() - if (!containsEntry(elem)) this - else { - markUpdated(elem, true) - later removeEntry elem - later - } - } - - override def size: Int = synchronized { - var m = this - var cnt = 0 - var s = 0 - while (m.later != null) { - if (m.deleted) s += 1 else s -= 1 - cnt += 1 - m = m.later - } - s += m.tableSize - if (cnt > logLimit) makeCopy(m) - s - } - - override def elements = synchronized { - makeCopyIfUpdated() - // note need to cache because (later versions of) set might be mutated while elements are traversed. - val cached = new mutable.ArrayBuffer() ++ super.elements - cached.elements - } - - override def newBuilder[B]: generic.Builder[HashSet, B] = - new AddableBuilder[HashSet, B](HashSet.empty) - - private def logLimit: Int = Math.sqrt(table.length).toInt - - private def markUpdated(elem: A, del: Boolean) { - val lv = loadFactor - later = new HashSet[A] { - override def initialSize = 0 - override def loadFactor = lv - table = HashSet.this.table - tableSize = HashSet.this.tableSize - threshold = HashSet.this.threshold - } - changedElem = elem - deleted = del - } - - private def makeCopy(last: HashSet[A]) { - def undo(m: HashSet[A]) { - if (m ne last) { - undo(m.later) - if (m.deleted) addEntry(m.changedElem) - else removeEntry(m.changedElem) - } - } - table = new scala.Array[AnyRef](last.table.length) - scala.Array.copy(last.table, 0, table, 0, table.length) - tableSize = last.tableSize - threshold = last.threshold - undo(this) - later = null - } - - private def makeCopyIfUpdated() { - var m = this - while (m.later != null) m = m.later - if (m ne this) makeCopy(m) - } -} - diff --git a/src/library/scalax/collection/immutable/Iterable.scala b/src/library/scalax/collection/immutable/Iterable.scala deleted file mode 100644 index 0e6bb8fae0..0000000000 --- a/src/library/scalax/collection/immutable/Iterable.scala +++ /dev/null @@ -1,24 +0,0 @@ -package scalax.collection.immutable - -import generic._ -import annotation.unchecked.uncheckedVariance - -/** Collection classes mixing in this class provide a method - * <code>elements</code> which returns an iterator over all the - * elements contained in the collection. - * - * @note If a collection has a known <code>size</code>, it should also sub-type <code>SizedIterable</code>. - * - * @author Matthias Zenger - * @autor Martin Odersky - * @owner Martin Odersky - * @version 2.8 - */ -trait Iterable[+A] extends collection.Iterable[A] - with IterableTemplate[Iterable, A @uncheckedVariance] - -object Iterable extends IterableFactory[Iterable] with EmptyIterableFactory[Iterable] { - val empty: Iterable[Nothing] = Nil -} - - diff --git a/src/library/scalax/collection/immutable/Map.scala b/src/library/scalax/collection/immutable/Map.scala deleted file mode 100755 index 923866fb8e..0000000000 --- a/src/library/scalax/collection/immutable/Map.scala +++ /dev/null @@ -1,66 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Set.scala 16893 2009-01-13 13:09:22Z cunei $ - - -package scalax.collection.immutable - -import generic._ - -object Map extends MapFactory[Map] { - private val hashSeed = "Map".hashCode - def empty[A, B]: Map[A, B] = new EmptyMap[A, B] -} - -trait Map[A, B] extends MapTemplate[A, B, Map] with collection.Map[A, B] { self => - - def empty[B]: Map[A, B] = new EmptyMap[A, B] - - /** The same map with a given default function */ - def withDefault(d: A => B): Map[A, B] = new Map[A, B] { - def size = self.size - def get(key: A) = self.get(key) - def elements = self.elements - override def empty[C] = self.empty - def update (key: A, value: B): Map[A, B] = - self update (key, value) withDefault d - def - (key: A): Map[A, B] = - self - key withDefault d - override def default(key: A): B = d(key) - } - - /** The same map with a given default value */ - def withDefaultValue(d: B): Map[A, B] = withDefault(x => d) - - /** Compares this set with another object and returns true, iff the - * other object is also a set which contains the same elements as - * this set. - * - * @param that the other object - * @note not necessarily run-time type safe. - * @return <code>true</code> iff this set and the other set - * contain the same elements. - */ - override def equals(that: Any): Boolean = that match { - case other: Map[a, b] => - this.size == other.size && this.forall { - case (key, value) => other.get(key.asInstanceOf[a]) match { - case None => false - case Some(otherval) => value == otherval - } - } - case _ => false - } - - /** A hash method compatible with <code>equals</code> - */ - override def hashCode() = - (Map.hashSeed /: this) (_ * 41 + _.hashCode) - -} diff --git a/src/library/scalax/collection/immutable/Map1.scala b/src/library/scalax/collection/immutable/Map1.scala deleted file mode 100755 index f518c7cf17..0000000000 --- a/src/library/scalax/collection/immutable/Map1.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Map1.scala 16893 2009-01-13 13:09:22Z cunei $ - - - -package scalax.collection.immutable - -/** This class implements immutable maps with exactly one entry - * - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Map1[A, B](key1: A, value1: B) extends Map[A, B] { - - def size = 1 - - def get(key: A): Option[B] = - if (key == key1) Some(value1) else None - - def elements = Iterator((key1, value1)) - - def update (key: A, value: B): Map[A, B] = - if (key == key1) new Map1(key1, value) - else null // new Map2(key1, value1, key, value) - - def - (key: A): Map[A, B] = - if (key == key1) empty else this -} - - - diff --git a/src/library/scalax/collection/immutable/Map2.scala b/src/library/scalax/collection/immutable/Map2.scala deleted file mode 100644 index f3f55c5828..0000000000 --- a/src/library/scalax/collection/immutable/Map2.scala +++ /dev/null @@ -1,44 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Map1.scala 16893 2009-01-13 13:09:22Z cunei $ - - - -package scalax.collection.immutable - -/** This class implements immutable maps with exactly one entry - * - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Map2[A, B](key1: A, value1: B, key2: A, value2: B) extends Map[A, B] { - - def size = 2 - - def get(key: A): Option[B] = - if (key == key1) Some(value1) - else if (key == key2) Some(value2) - else None - - def elements = Iterator((key1, value1), (key2, value2)) - - def update (key: A, value: B): Map[A, B] = - if (key == key1) new Map2(key1, value, key2, value2) - else if (key == key2) new Map2(key1, value1, key2, value) - else new Map3(key1, value1, key2, value2, key, value) - - def - (key: A): Map[A, B] = - if (key == key1) new Map1(key2, value2) - else if (key == key2) new Map1(key1, value1) - else this -} - - - diff --git a/src/library/scalax/collection/immutable/Map3.scala b/src/library/scalax/collection/immutable/Map3.scala deleted file mode 100644 index 3c8e6298cd..0000000000 --- a/src/library/scalax/collection/immutable/Map3.scala +++ /dev/null @@ -1,47 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Map1.scala 16893 2009-01-13 13:09:22Z cunei $ - - - -package scalax.collection.immutable - -/** This class implements immutable maps with exactly one entry - * - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Map3[A, B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B) extends Map[A, B] { - - def size = 3 - - def get(key: A): Option[B] = - if (key == key1) Some(value1) - else if (key == key2) Some(value2) - else if (key == key3) Some(value3) - else None - - def elements = Iterator((key1, value1), (key2, value2), (key3, value3)) - - def update (key: A, value: B): Map[A, B] = - if (key == key1) new Map3(key1, value, key2, value2, key3, value3) - else if (key == key2) new Map3(key1, value1, key2, value, key3, value3) - else if (key == key3) new Map3(key1, value1, key2, value2, key3, value) - else new Map4(key1, value1, key2, value2, key3, value3, key, value) - - def - (key: A): Map[A, B] = - if (key == key1) new Map2(key2, value2, key3, value3) - else if (key == key2) new Map2(key1, value1, key3, value3) - else if (key == key3) new Map2(key1, value1, key2, value2) - else this -} - - - diff --git a/src/library/scalax/collection/immutable/Map4.scala b/src/library/scalax/collection/immutable/Map4.scala deleted file mode 100644 index ad2dcd513b..0000000000 --- a/src/library/scalax/collection/immutable/Map4.scala +++ /dev/null @@ -1,50 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Map1.scala 16893 2009-01-13 13:09:22Z cunei $ - - - -package scalax.collection.immutable - -/** This class implements immutable maps with exactly one entry - * - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Map4[A, B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B, key4: A, value4: B) extends Map[A, B] { - - def size = 4 - - def get(key: A): Option[B] = - if (key == key1) Some(value1) - else if (key == key2) Some(value2) - else if (key == key3) Some(value3) - else if (key == key4) Some(value4) - else None - - def elements = Iterator((key1, value1), (key2, value2), (key3, value3), (key4, value4)) - - def update (key: A, value: B): Map[A, B] = - if (key == key1) new Map4(key1, value, key2, value2, key3, value3, key4, value4) - else if (key == key2) new Map4(key1, value1, key2, value, key3, value3, key4, value4) - else if (key == key3) new Map4(key1, value1, key2, value2, key3, value, key4, value4) - else if (key == key4) new Map4(key1, value1, key2, value2, key3, value3, key4, value) - else HashMap((key1, value1), (key2, value2), (key3, value3), (key4, value4), (key, value)) - - def - (key: A): Map[A, B] = - if (key == key1) new Map3(key2, value2, key3, value3, key4, value4) - else if (key == key2) new Map3(key1, value1, key3, value3, key4, value4) - else if (key == key3) new Map3(key1, value1, key2, value2, key4, value4) - else if (key == key4) new Map3(key1, value1, key2, value2, key3, value3) - else this -} - - - diff --git a/src/library/scalax/collection/immutable/OrderedIterable.scala b/src/library/scalax/collection/immutable/OrderedIterable.scala deleted file mode 100644 index 80fa418eec..0000000000 --- a/src/library/scalax/collection/immutable/OrderedIterable.scala +++ /dev/null @@ -1,26 +0,0 @@ -package scalax.collection.immutable - -import generic._ -import annotation.unchecked.uncheckedVariance - -/** Collection classes mixing in this class provide a method - * <code>elements</code> which returns an iterator over all the - * elements contained in the collection. - * - * @note If a collection has a known <code>size</code>, it should also sub-type <code>SizedIterable</code>. - * - * @author Matthias Zenger - * @autor Martin Odersky - * @owner Martin Odersky - * @version 2.8 - */ -trait OrderedIterable[+A] extends immutable.Iterable[A] - with OrderedIterableTemplate[OrderedIterable, A @uncheckedVariance] - with collection.OrderedIterable[A] - -object OrderedIterable extends IterableFactory[OrderedIterable] - with EmptyIterableFactory[OrderedIterable] { - val empty: OrderedIterable[Nothing] = Nil -} - - diff --git a/src/library/scalax/collection/immutable/Sequence.scala b/src/library/scalax/collection/immutable/Sequence.scala deleted file mode 100644 index 78de3cbfaf..0000000000 --- a/src/library/scalax/collection/immutable/Sequence.scala +++ /dev/null @@ -1,25 +0,0 @@ -package scalax.collection.immutable - -import generic._ -import annotation.unchecked.uncheckedVariance - -/** Collection classes mixing in this class provide a method - * <code>elements</code> which returns an iterator over all the - * elements contained in the collection. - * - * @note If a collection has a known <code>size</code>, it should also sub-type <code>SizedIterable</code>. - * - * @author Matthias Zenger - * @autor Martin Oderskyter - * @owner Martin Odersky - * @version 2.8 - */ -trait Sequence[+A] extends OrderedIterable[A] - with SequenceTemplate[Sequence, A @uncheckedVariance] - with collection.Sequence[A] - -object Sequence extends SequenceFactory[Sequence] with EmptyIterableFactory[Sequence] { - val empty: Sequence[Nothing] = Nil -} - - diff --git a/src/library/scalax/collection/immutable/Set.scala b/src/library/scalax/collection/immutable/Set.scala deleted file mode 100755 index 9462cd3c5f..0000000000 --- a/src/library/scalax/collection/immutable/Set.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Set.scala 16893 2009-01-13 13:09:22Z cunei $ - - -package scalax.collection.immutable - -import generic._ - -object Set extends generic.SetFactory[Set] { - private val hashSeed = "Set".hashCode - def empty[A]: Set[A] = new EmptySet[A] -} - -trait Set[A] extends OrderedIterable[A] - with collection.Set[A] - with SetTemplate[Set, A] { - - override def newBuilder[B]: Builder[Set, B] = Set.newBuilder[B] - - /** Compares this set with another object and returns true, iff the - * other object is also a set which contains the same elements as - * this set. - * - * @param that the other object - * @note not necessarily run-time type safe. - * @return <code>true</code> iff this set and the other set - * contain the same elements. - */ - override def equals(that: Any): Boolean = that match { - case other: Set[_] => - this.size == other.size && subsetOf(other.asInstanceOf[Set[A]]) - case _ => - false - } - - override def hashCode = (Set.hashSeed /: this)(_ * 41 + _.hashCode) - -} diff --git a/src/library/scalax/collection/immutable/Set1.scala b/src/library/scalax/collection/immutable/Set1.scala deleted file mode 100755 index 276cd83bb0..0000000000 --- a/src/library/scalax/collection/immutable/Set1.scala +++ /dev/null @@ -1,46 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Set1.scala 16893 2009-01-13 13:09:22Z cunei $ - - - -package scalax.collection.immutable - -import collection.generic.Builder - -/** This class implements immutable sets with exactly one element. - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Set1[A](elem1: A) extends Set[A] { - - def size: Int = 1 - - def contains(elem: A): Boolean = - elem == elem1 - - def + (elem: A): Set[A] = - if (contains(elem)) this - else new Set2(elem1, elem) - - def - (elem: A): Set[A] = - if (elem == elem1) new EmptySet[A] - else this - - def elements: Iterator[A] = - Iterator(elem1) - - override def foreach(f: A => Unit): Unit = { - f(elem1) - } -} - - - diff --git a/src/library/scalax/collection/immutable/Set2.scala b/src/library/scalax/collection/immutable/Set2.scala deleted file mode 100755 index 828c52d053..0000000000 --- a/src/library/scalax/collection/immutable/Set2.scala +++ /dev/null @@ -1,47 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Set1.scala 16893 2009-01-13 13:09:22Z cunei $ - - - -package scalax.collection.immutable - -import collection.generic.Builder - -/** This class implements immutable sets with exactly one element. - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Set2[A](elem1: A, elem2: A) extends Set[A] { - - def size: Int = 2 - - def contains(elem: A): Boolean = - elem == elem1 || elem == elem2 - - def + (elem: A): Set[A] = - if (contains(elem)) this - else new Set3(elem1, elem2, elem) - - def - (elem: A): Set[A] = - if (elem == elem1) new Set1(elem2) - else if (elem == elem2) new Set1(elem1) - else this - - def elements: Iterator[A] = - Iterator(elem1, elem2) - - override def foreach(f: A => Unit): Unit = { - f(elem1); f(elem2) - } -} - - - diff --git a/src/library/scalax/collection/immutable/Set3.scala b/src/library/scalax/collection/immutable/Set3.scala deleted file mode 100755 index f14253231f..0000000000 --- a/src/library/scalax/collection/immutable/Set3.scala +++ /dev/null @@ -1,48 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Set1.scala 16893 2009-01-13 13:09:22Z cunei $ - - - -package scalax.collection.immutable - -import collection.generic.Builder - -/** This class implements immutable sets with exactly one element. - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Set3[A](elem1: A, elem2: A, elem3: A) extends Set[A] { - - def size: Int = 3 - - def contains(elem: A): Boolean = - elem == elem1 || elem == elem2 || elem == elem3 - - def + (elem: A): Set[A] = - if (contains(elem)) this - else new Set4(elem1, elem2, elem3, elem) - - def - (elem: A): Set[A] = - if (elem == elem1) new Set2(elem2, elem3) - else if (elem == elem2) new Set2(elem1, elem3) - else if (elem == elem3) new Set2(elem1, elem2) - else this - - def elements: Iterator[A] = - Iterator(elem1, elem2, elem3) - - override def foreach(f: A => Unit): Unit = { - f(elem1); f(elem2); f(elem3) - } -} - - - diff --git a/src/library/scalax/collection/immutable/Set4.scala b/src/library/scalax/collection/immutable/Set4.scala deleted file mode 100755 index bef1b6588d..0000000000 --- a/src/library/scalax/collection/immutable/Set4.scala +++ /dev/null @@ -1,49 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Set1.scala 16893 2009-01-13 13:09:22Z cunei $ - - - -package scalax.collection.immutable - -import collection.generic.Builder - -/** This class implements immutable sets with exactly one element. - * @author Martin Oderskty - * @version 1.0, 019/01/2007 - */ -@serializable -class Set4[A](elem1: A, elem2: A, elem3: A, elem4: A) extends Set[A] { - - def size: Int = 4 - - def contains(elem: A): Boolean = - elem == elem1 || elem == elem2 || elem == elem3 || elem == elem4 - - def + (elem: A): Set[A] = - if (contains(elem)) this - else new DefaultSet[A] + (elem1, elem2, elem3, elem4, elem) - - def - (elem: A): Set[A] = - if (elem == elem1) new Set3(elem2, elem3, elem4) - else if (elem == elem2) new Set3(elem1, elem3, elem4) - else if (elem == elem3) new Set3(elem1, elem2, elem4) - else if (elem == elem4) new Set3(elem1, elem2, elem3) - else this - - def elements: Iterator[A] = - Iterator(elem1, elem2, elem3, elem4) - - override def foreach(f: A => Unit): Unit = { - f(elem1); f(elem2); f(elem3); f(elem4) - } -} - - - diff --git a/src/library/scalax/collection/immutable/Stream.scala b/src/library/scalax/collection/immutable/Stream.scala deleted file mode 100755 index 4055be40bc..0000000000 --- a/src/library/scalax/collection/immutable/Stream.scala +++ /dev/null @@ -1,794 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Stream.scala 16287 2008-10-18 13:41:36Z nielsen $ - - -package scalax.collection.immutable - -import mutable.ListBuffer -import generic.{SequenceTemplate, SequenceFactory, EmptyIterableFactory, Builder, LazyBuilder} -import annotation.unchecked.uncheckedVariance -import annotation.tailrec - -/** - * The object <code>Stream</code> provides helper functions - * to manipulate streams. - * - * @author Martin Odersky, Matthias Zenger - * @version 1.1 08/08/03 - */ -object Stream extends SequenceFactory[Stream] with EmptyIterableFactory[Stream] { - - import collection.{Iterable, OrderedIterable, Sequence, Vector} - - override val empty: Stream[Nothing] = Nil - override def apply[A](xs: A*) = xs.asInstanceOf[Iterable[A]].toList // !@! - override def newBuilder[B]: Builder[Stream, B] = new ListBuffer[B] - - class ConsWrapper[A](tl: => Stream[A]) { - def #::(hd: A): Stream[A] = new Cons(hd, tl) - def #:::(prefix: Stream[A]): Stream[A] = prefix append tl - } - - implicit def consWrapper[A](stream: => Stream[A]): ConsWrapper[A] = - new ConsWrapper[A](stream) - - object #:: { - def unapply[A](xs: Stream[A]): Option[(A, Stream[A])] = - if (xs.isEmpty) None - else Some(xs.head, xs.tail) - } - - /** @deprecated use #:: instead */ - @deprecated lazy val lazy_:: = #:: - - /** An alternative way of building and matching Streams using Stream.cons(hd, tl). - */ - object cons { - - /** A stream consisting of a given first element and remaining elements - * @param hd The first element of the result stream - * @param tl The remaining elements of the result stream - */ - def apply[A](hd: A, tl: => Stream[A]) = new Cons(hd, tl) - - /** Maps a stream to its head and tail */ - def unapply[A](xs: Stream[A]): Option[(A, Stream[A])] = #::.unapply(xs) - } - - final class Cons[+A](hd: A, tl: => Stream[A]) extends Stream[A] { - override def isEmpty = false - override def head = hd - private[this] var tlVal: Stream[A] = _ - private def tlDefined = tlVal ne null - override def tail: Stream[A] = { - if (!tlDefined) { tlVal = tl } - tlVal - } - override def hasDefiniteSize = tlDefined && tlVal.hasDefiniteSize - - // Overridden methods from IterableTemplate or overloaded variants of such methods - - /** Create a new stream which contains all elements of this stream - * followed by all elements of Iterable `that' - */ - override def ++[B >: A](that: Iterable[B]): Stream[B] = this append that - - /** Create a new stream which contains all elements of this stream - * followed by all elements of Iterator `that' - */ - override def ++[B >: A](that: Iterator[B]): Stream[B] = this append that.toStream - - /** Returns the stream resulting from applying the given function - * <code>f</code> to each element of this stream. - * - * @param f function to apply to each element. - * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> if this - * sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>. - */ - override def map[B](f: A => B): Stream[B] = - new Cons(f(head), tail map f) - - /** Applies the given function <code>f</code> to each element of - * this stream, then concatenates the results. - * - * @param f the function to apply on each element. - * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if - * this stream is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>. - */ - override def flatMap[B](f: A => Iterable[B]): Stream[B] = { - // drops A's for which f yields an empty Iterable[B] - def loop(s: Stream[A]): Stream[B] = - if (s.isEmpty) Nil - else { - val i = f(s.head) - if (i.isEmpty) loop(s.tail) - else i.toStream append loop(s.tail) - } - loop(this) - } - - /** Returns all the elements of this stream that satisfy the - * predicate <code>p</code>. The order of the elements is preserved. - * - * @param p the predicate used to filter the stream. - * @return the elements of this stream satisfying <code>p</code>. - */ - override def filter(p: A => Boolean): Stream[A] = { - // drops A's for which p yields false - def loop(s: Stream[A]): Stream[A] = - if (s.isEmpty) Nil - else { - val b = p(s.head) - if (!b) loop(s.tail) - else new Cons(s.head, tail filter p) - } - loop(this) - } - - /** Returns all the elements of this stream that satisfy the - * predicate <code>p</code>. The order of the elements is preserved. - * - * @param p the predicate used to filter the stream. - * @return the elements of this stream satisfying <code>p</code>. - */ - override def partition(p: A => Boolean): (Stream[A], Stream[A]) = (filter(p(_)), remove(p(_))) - - /** Returns a stream formed from this stream and the specified stream - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * If one of the two streams is longer than the other, its remaining elements are ignored. - * - * @return <code>Stream({a<sub>0</sub>,b<sub>0</sub>}, ..., - * {a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>)}</code> when - * <code>Stream(a<sub>0</sub>, ..., a<sub>m</sub>) - * zip Stream(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked. - */ - def zip[B](that: Stream[B]): Stream[(A, B)] = - if (that.isEmpty) empty - else new Cons((this.head, that.head), this.tail zip that.tail) - - /** Returns a list formed from this list and the specified list - * <code>that</code> by associating each element of the former with - * the element at the same position in the latter. - * - * @param that list <code>that</code> may have a different length - * as the self list. - * @param thisElem element <code>thisElem</code> is used to fill up the - * resulting list if the self list is shorter than - * <code>that</code> - * @param thatElem element <code>thatElem</code> is used to fill up the - * resulting list if <code>that</code> is shorter than - * the self list - * @return <code>List((a<sub>0</sub>,b<sub>0</sub>), ..., - * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>), - * ..., {elem,b<sub>m</sub>})</code> - * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip - * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is - * invoked where <code>m > n</code>. - */ - def zipAll[B, A1 >: A, B1 >: B](that: Stream[B], thisElem: A1, thatElem: B1): Stream[(A1, B1)] = { - if (that.isEmpty) new Cons((this.head, thatElem), this.tail.zipAll(that, thisElem, thatElem)) - else new Cons((this.head, that.head), this.tail.zipAll(that.tail, thisElem, thatElem)) - } - - /** Zips this iterable with its indices. `s.zipWithIndex` is equivalent to - * `s zip s.indices` - */ - override def zipWithIndex = this zip (Iterator.from(0).toStream) - - /** Write all defined elements of this iterable into given string builder. - * The written text begins with the string <code>start</code> and is finished by the string - * <code>end</code>. Inside, the string representations of defined elements (w.r.t. - * the method <code>toString()</code>) are separated by the string - * <code>sep</code>. The method will not force evaluation of undefined elements. A - * tail of such elements will be represented by a "?" instead. - */ - override def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = { - b append start append hd - if (tlDefined) tlVal.addString(b, sep, sep, end) - else b append ", ?" append end - } - - /** Returns the <code>n</code> first elements of this stream, or else the whole - * stream, if it has less than <code>n</code> elements. - * - * @param n the number of elements to take. - * @return the <code>n</code> first elements of this stream. - */ - override def take(n: Int): Stream[A] = - if (n <= 0) Nil else new Cons(head, tail take (n-1)) - - /** Returns the stream without its <code>n</code> first elements. - * If the stream has less than <code>n</code> elements, the empty stream is returned. - * - * @param n the number of elements to drop. - * @return the stream without its <code>n</code> first elements. - */ - override def drop(n: Int): Stream[A] = { - var these: Stream[A] = this - var i = n - while (!these.isEmpty && i > 0) { - these = these.tail - i -= 1 - } - these - } - - /** A substream starting at index `from` - * and extending up to (but not including) index `until`. - * - * @This 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 - * @throws IndexOutOfBoundsException if <code>from < 0</code> - * or <code>length < from + len<code> - * @note Might return different results for different runs, unless this iterable is ordered - */ - override def slice(from: Int, to: Int): Stream[A] = - this.drop(from).take(to - from) - - /** The stream without its last element. - * @throws Predef.UnsupportedOperationException if the stream is empty. - */ - override def init: Stream[A] = - if (tail.isEmpty) Nil - else new Cons(head, tail.init) - - /** Returns the rightmost <code>n</code> elements from this iterable. - * @param n the number of elements to take - */ - override def takeRight(n: Int): Stream[A] = { - var these: Stream[A] = this - var lead = this drop n - while (!lead.isEmpty) { - these = these.tail - lead = lead.tail - } - these - } - - /** Returns the longest prefix of this stream whose elements satisfy - * the predicate <code>p</code>. - * - * @param p the test predicate. - */ - override def takeWhile(p: A => Boolean): Stream[A] = - if (p(head)) new Cons(head, tail takeWhile p) else Nil - - - /** Returns the longest suffix of this iterable whose first element - * does not satisfy the predicate <code>p</code>. - * - * @param p the test predicate. - */ - override def dropWhile(p: A => Boolean): Stream[A] = { - var these: Stream[A] = this - while (!these.isEmpty && p(these.head)) these = these.tail - these - } - - /** Returns a pair consisting of the longest prefix of the stream whose - * elements all satisfy the given predicate, and the rest of the stream. - * - * @param p the test predicate - */ - override def span(p: A => Boolean): (List[A], Stream[A]) = { - var these: Stream[A] = this - val l = new ListBuffer[A] - while (!these.isEmpty && p(these.head)) { - l += these.head - these = these.tail - } - (l.toList, these) - } - - // Overridden methods from Sequence - - /** Builds a new stream from this stream in which any duplicates (wrt to ==) removed. - * Among duplicate elements, only the first one is retained in the result stream - */ - override def removeDuplicates: Stream[A] = - new Cons(head, tail.filter(head !=).removeDuplicates) - - /** Returns a new sequence of given length containing the elements of this sequence followed by zero - * or more occurrences of given elements. - */ - override def padTo[B >: A](len: Int, elem: B): Stream[B] = - new Cons(head, tail.padTo(len - 1, elem)) - } - - /** - * Create an infinite stream starting at <code>start</code> - * and incrementing by step <code>step</code> - * - * @param start the start value of the stream - * @param step the increment value of the stream - * @return the stream starting at value <code>start</code>. - */ - def from(start: Int, step: Int): Stream[Int] = - new Cons(start, from(start+step, step)) - - /** - * Create an infinite stream starting at <code>start</code> - * and incrementing by 1. - * - * @param start the start value of the stream - * @return the stream starting at value <code>start</code>. - */ - def from(start: Int): Stream[Int] = from(start, 1) - - /** - * Create an infinite stream containing the given element expression (which is computed for each - * occurrence) - * @param elem the element composing the resulting stream - * @return the stream containing an inifinite number of elem - * @deprecated use fill instead - */ - @deprecated def fill[A](elem: => A): Stream[A] = new Cons(elem, fill(elem)) - - /** A stream containing all elements of a given iterator, in the order they are produced. - * @param it The iterator producing the stream's elements - * @deprecated use it.toStream instead - */ - @deprecated def fromIterator[A](it: Iterator[A]): Stream[A] = - if (it.hasNext) cons(it.next, fromIterator(it)) else empty - - /** The concatenation of a sequence of streams - * @deprecated use xs.flatten instead - */ - @deprecated def concat[A](xs: Iterable[Stream[A]]): Stream[A] = concat(xs.elements) - - /** The concatenation of all streams returned by an iterator - * @deprecated use xs.toStream.flatten instead - */ - @deprecated def concat[A](xs: Iterator[Stream[A]]): Stream[A] = - if (xs.hasNext) xs.next append concat(xs) - else empty - - /** - * Create a stream with element values - * <code>v<sub>n+1</sub> = step(v<sub>n</sub>)</code> - * where <code>v<sub>0</sub> = start</code> - * and elements are in the range between <code>start</code> (inclusive) - * and <code>end</code> (exclusive) - * @deprecated use @see iterate instead. - * @param start the start value of the stream - * @param end the end value of the stream - * @param step the increment function of the stream, must be monotonically increasing or decreasing - * @return the stream starting at value <code>start</code>. - */ - @deprecated def range(start: Int, end: Int, step: Int => Int): Stream[Int] = { - val up = step(start) > start - val down = step(start) < start - def loop(lo: Int): Stream[Int] = - if ((!up || lo < end) && (!down || lo > end)) cons(lo, loop(step(lo))) - else empty - loop(start) - } - - /** - * Create an infinite stream containing the given element. - * - * @param elem the element composing the resulting stream - * @return the stream containing an inifinite number of elem - * @deprecated use fill(elem) instead - */ - @deprecated def const[A](elem: A): Stream[A] = cons(elem, const(elem)) - - /** Create a stream containing several copies of an element. - * - * @param n the length of the resulting stream - * @param elem the element composing the resulting stream - * @return the stream composed of n elements all equal to elem - * @deprecated use fill(n, elem) instead - */ - @deprecated def make[A](n: Int, elem: A): Stream[A] = - const(elem) take n -} - -import Stream._ - -/** - * <p>The class <code>Stream</code> implements lazy lists where elements - * are only evaluated when they are needed. Here is an example:</p> - * <pre> - * <b>object</b> Main <b>extends</b> Application { - * - * <b>def</b> from(n: Int): Stream[Int] = - * Stream.cons(n, from(n + 1)) - * - * <b>def</b> sieve(s: Stream[Int]): Stream[Int] = - * Stream.cons(s.head, sieve(s.tail filter { _ % s.head != 0 })) - * - * <b>def</b> primes = sieve(from(2)) - * - * primes take 10 print - * } - * </pre> - * - * @author Martin Odersky, Matthias Zenger - * @version 1.1 08/08/03 - */ -abstract class Stream[+A] extends Sequence[A] - with SequenceTemplate[Stream, A @uncheckedVariance] { -self => - - import collection.{Iterable, OrderedIterable, Sequence, Vector} - - /** is this stream empty? */ - def isEmpty: Boolean - - /** The first element of this stream - * @throws Predef.NoSuchElementException if the stream is empty. - */ - def head: A - - /** A stream consisting of the remaining elements of this stream after the first one. - * @throws Predef.UnsupportedOperationException if the stream is empty. - */ - def tail: Stream[A] - - // Implementation of abstract methods - - /** Create a new @see LazyBuilder to build a stream */ - def newBuilder[B]: Builder[Stream, B] = new LazyBuilder[Stream, B] { - def result: Stream[B] = elements.toStream - } - - /** Returns the number of elements in the list. - */ - def length: Int = { - var these = self - var len = 0 - while (!these.isEmpty) { - len += 1 - these = these.tail - } - len - } - - /** Returns the <code>n</code>-th element of this stream. The first element - * (head of the stream) is at position 0. - * - * @param n index of the element to return - * @return the element at position <code>n</code> in this stream. - * @throws Predef.NoSuchElementException if the stream is too short. - */ - override def apply(n: Int): A = drop(n).head - - // New methods in Stream - - /** The stream resulting from the concatenation of this stream with the argument stream. - * @param rest The stream that gets appended to this stream - */ - def append[B >: A](rest: => Iterable[B]): Stream[B] = - if (isEmpty) rest.toStream else new Cons(head, tail append rest) - - /** Force evaluation of the whole stream and return it */ - def force: Stream[A] = { - var these = this - while (!isEmpty) these = these.tail - this - } - - /** Prints elements of this stream one by one, separated by commas */ - def print() { print(", ") } - - /** Prints elements of this stream one by one, separated by <code>sep</code> - * @param sep The separator string printed between consecutive elements. - */ - def print(sep: String) { - @tailrec - def loop(these: Stream[A], start: String) { - Console.print(start) - if (isEmpty) Console.print("empty") - else { - Console.print(these.head) - loop(these.tail, sep) - } - } - loop(this, "") - } - - // Overridden methods from IterableTemplate or overloaded variants of such methods - - /** Returns the elements in the sequence as an iterator - */ - override def elements: Iterator[A] = new Iterator[A] { - var these = self - def hasNext: Boolean = !these.isEmpty - def next: A = - if (hasNext) { - val result = these.head; these = these.tail; result - } else Iterator.empty.next - override def toList: List[A] = these.toList - } - - /** Apply the given function <code>f</code> to each element of this stream - * (while respecting the order of the elements). - * - * @param f the treatment to apply to each element. - */ - override def foreach(f: A => Unit) { - var these = this - while (!these.isEmpty) { - f(these.head) - these = these.tail - } - } - - /** Tests if the predicate <code>p</code> is satisfied by all elements - * in this list. - * - * !!! todo: perform speed with inherited version from Iterable, and drop - * if not significantly better - * @param p the test predicate. - * @return <code>true</code> iff all elements of this list satisfy the - * predicate <code>p</code>. - */ - override def forall(p: A => Boolean): Boolean = { - var these = this - while (!these.isEmpty) { - if (!p(these.head)) return false - these = these.tail - } - true - } - - /** Tests the existence in this list of an element that satisfies the - * predicate <code>p</code>. - * - * !!! todo: perform speed with inherited version from Iterable, and drop - * if not significantly better - * @param p the test predicate. - * @return <code>true</code> iff there exists an element in this list that - * satisfies the predicate <code>p</code>. - */ - override def exists(p: A => Boolean): Boolean = { - var these = this - while (!these.isEmpty) { - if (p(these.head)) return true - these = these.tail - } - false - } - - /** Count the number of elements in the iterable which satisfy a predicate. - * - * !!! todo: perform speed with inherited version from Iterable, and drop - * if not significantly better - * @param p the predicate for which to count - * @return the number of elements satisfying the predicate <code>p</code>. - */ - override def count(p: A => Boolean): Int = { - var these = this - var cnt = 0 - while (!these.isEmpty) { - if (p(these.head)) cnt += 1 - these = these.tail - } - cnt - } - - /** Find and return the first element of the list satisfying a - * predicate, if any. - * - * !!! todo: perform speed with inherited version from Iterable, and drop - * if not significantly better - * @param p the predicate - * @return the first element in the list satisfying <code>p</code>, - * or <code>None</code> if none exists. - */ - override def find(p: A => Boolean): Option[A] = { - var these = this - while (!these.isEmpty) { - if (p(these.head)) return Some(these.head) - these = these.tail - } - None - } - - /** Combines the elements of this list together using the binary - * function <code>f</code>, from left to right, and starting with - * the value <code>z</code>. - * - * !!! todo: perform speed with inherited version from Iterable, and drop - * if not significantly better - * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...), - * a<sub>n</sub>)</code> if the list is - * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>. - */ - override def foldLeft[B](z: B)(f: (B, A) => B): B = { - var acc = z - var these = this - while (!these.isEmpty) { - acc = f(acc, these.head) - these = these.tail - } - acc - } - - /** Combines the elements of this list together using the binary - * function <code>f</code>, from right to left, and starting with - * the value <code>z</code>. - * - * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code> - * if the list is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>. - */ - override def foldRight[B](z: B)(f: (A, B) => B): B = - if (this.isEmpty) z - else f(head, tail.foldRight(z)(f)) - - /** Combines the elements of this list together using the binary - * operator <code>op</code>, from left to right - * @param op The operator to apply - * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code> - if the list has elements - * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>. - * @throws Predef.UnsupportedOperationException if the list is empty. - */ - override def reduceLeft[B >: A](f: (B, A) => B): B = - if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft") - else tail.foldLeft[B](head)(f) - - /** Combines the elements of this iterable object together using the binary - * operator <code>op</code>, from right to left - * @note Will not terminate for infinite-sized collections. - * @param op The operator to apply - * - * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code> - * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ..., - * a<sub>n</sub></code>. - * - * @throws Predef.UnsupportedOperationException if the iterator is empty. - */ - override def reduceRight[B >: A](op: (A, B) => B): B = - if (isEmpty) throw new UnsupportedOperationException("Nil.reduceRight") - else if (tail.isEmpty) head - else op(head, tail.reduceRight(op)) - - /** - * Create a stream which contains all the elements of this iterable object. - * @note consider using <code>projection</code> for lazy behavior. - */ - override def toStream: Stream[A] = this - - /** Defines the prefix of this object's <code>toString</code> representation as ``Stream''. - */ - override def stringPrefix = "Stream" - - /** The last element of this stream. - * - * @throws Predef.NoSuchElementException if the stream is empty. - */ - override def last: A = { - if (isEmpty) throw new NoSuchElementException - var these = this - var nx = these.tail - while (!nx.isEmpty) { - these = nx - nx = nx.tail - } - these.head - } - - /** Returns the rightmost <code>n</code> elements from this iterable. - * @param n the number of elements to take - */ - override def dropRight(n: Int): List[A] = { - val b = new ListBuffer[A] - var these = this - var lead = this drop n - while (!lead.isEmpty) { - b += these.head - these = these.tail - lead = lead.tail - } - b.toList - } - - /** Returns true iff the other stream contains the same elements as this one. - * - * @note will not terminate for two infinite-sized streams. - * @param that the other stream - */ - def sameElements[B >: A](that: Stream[B]): Boolean = { - val these = this - val those = that - while (!these.isEmpty && !those.isEmpty && these.head == those.head) {} - these.isEmpty && those.isEmpty - } - - // Overridden methods from Sequence - - /** Result of comparing <code>length</code> with operand <code>len</code>. - * returns <code>x</code> where - * <code>x < 0</code> iff <code>this.length < len</code> - * <code>x == 0</code> iff <code>this.length == len</code> - * <code>x > 0</code> iff <code>this.length > len</code>. - */ - override def lengthCompare(len: Int): Int = { - var i = 0 - var these = self - while (!these.isEmpty && i <= len) { - i += 1 - these = these.tail - } - i - len - } - - /** Is this partial function defined for the index <code>x</code>? - */ - override def isDefinedAt(x: Int): Boolean = x >= 0 && lengthCompare(x) >= 0 - - /** 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 - */ - override def segmentLength(p: A => Boolean, from: Int): Int = { - var i = from - var these = this drop from - while (!these.isEmpty && p(these.head)) { - i += 1 - these = these.tail - } - i - } - - /** Returns index of the first element starting from a start index - * satisying a predicate, or -1, if none exists. - * - * @note may not terminate for infinite-sized streams. - * @param p the predicate - * @param from the start index - */ - override def indexWhere(p: A => Boolean, from: Int): Int = { - var i = from - var these = this drop from - while (!these.isEmpty && !p(these.head)) { - i += 1 - these = these.tail - } - if (these.isEmpty) -1 else i - } - - /** Returns index of the last element satisying a predicate, or -1, if none exists. - * - * @param p the predicate - * @return the index of the last element satisfying <code>p</code>, - * or -1 if such an element does not exist - */ - override def lastIndexWhere(p: A => Boolean, end: Int): Int = { - var i = 0 - var these = this - var last = -1 - while (!these.isEmpty && i <= end) { - if (p(these.head)) last = i - } - i - } - - /** A list consisting of all elements of this list in reverse order. - */ - override def reverse: List[A] = { - var result: List[A] = Nil - var these = this - while (!these.isEmpty) { - result = these.head :: result - these = these.tail - } - result - } -} - diff --git a/src/library/scalax/collection/immutable/Vector.scala b/src/library/scalax/collection/immutable/Vector.scala deleted file mode 100644 index 93e9601bd2..0000000000 --- a/src/library/scalax/collection/immutable/Vector.scala +++ /dev/null @@ -1,25 +0,0 @@ -package scalax.collection.immutable - -import generic._ -import annotation.unchecked.uncheckedVariance - -/** Collection classes mixing in this class provide a method - * <code>elements</code> which returns an iterator over all the - * elements contained in the collection. - * - * @note If a collection has a known <code>size</code>, it should also sub-type <code>SizedIterable</code>. - * // !!! todo: insert good immutable vector implementation here. - * @author Matthias Zenger - * @autor Martin Odersky - * @owner Martin Odersky - * @version 2.8 - */ -trait Vector[+A] extends Sequence[A] - with VectorTemplate[Vector, A @uncheckedVariance] - with collection.Vector[A] - -object Vector extends SequenceFactory[Vector] with EmptyIterableFactory[Vector] { - val empty: Vector[Nothing] = immutable.Vector.empty -} - - diff --git a/src/library/scalax/collection/mutable/Array.scala b/src/library/scalax/collection/mutable/Array.scala deleted file mode 100755 index cf1e02008b..0000000000 --- a/src/library/scalax/collection/mutable/Array.scala +++ /dev/null @@ -1,410 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Array.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.collection.mutable - -import scalax.collection.generic._ -import compat.Platform.arraycopy - -/** This object contains utility methods operating on arrays. - * - * @author Martin Odersky - * @version 1.0 - */ -object Array extends SequenceFactory[Array] { - - /** Copy one array to another. - * Equivalent to - * <code>System.arraycopy(src, srcPos, dest, destPos, length)</code>, - * except that this works also for polymorphic and boxed arrays. - * - * @param src ... - * @param srcPos ... - * @param dest ... - * @param destPos ... - * @param length ... - */ - def copy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int) { - src match { - case xs: runtime.BoxedArray[_] => - xs.copyTo(srcPos, dest, destPos, length) - case _ => - dest match { - case xs: runtime.BoxedArray[_] => - xs.copyFrom(src, srcPos, destPos, length) - case _ => - def fillDest[T](da: Array[T], sa: Int=>T) { - var d = destPos - for (s <- srcPos to srcPos+length-1) { - da(d) = sa(s); d += 1 - } - } - if (dest.isInstanceOf[Array[Any]]) { - def fill(sa: Int=>Any) = fillDest(dest.asInstanceOf[Array[Any]], sa) - src match { - case sa:Array[Int] => fill(s=>Int.box(sa(s))) -/*!!! - case sa:Array[Long] => fill(s=>Long.box(sa(s))) - case sa:Array[Char] => fill(s=>Char.box(sa(s))) - case sa:Array[Boolean] => fill(s=>Boolean.box(sa(s))) - case sa:Array[Byte] => fill(s=>Byte.box(sa(s))) - case sa:Array[Short] => fill(s=>Short.box(sa(s))) - case sa:Array[Double] => fill(s=>Double.box(sa(s))) - case sa:Array[Float] => fill(s=>Float.box(sa(s))) -*/ - case _ => arraycopy(src, srcPos, dest, destPos, length) - } - } else if (dest.isInstanceOf[Array[AnyVal]]) { - def fill(sa: Int=>AnyVal) = fillDest(dest.asInstanceOf[Array[AnyVal]], sa) - src match { - case sa:Array[Int] => fill(sa(_)) -/*!!! - case sa:Array[Long] => fill(sa(_)) - case sa:Array[Char] => fill(sa(_)) - case sa:Array[Boolean] => fill(sa(_)) - case sa:Array[Byte] => fill(sa(_)) - case sa:Array[Short] => fill(sa(_)) - case sa:Array[Double] => fill(sa(_)) - case sa:Array[Float] => fill(sa(_)) -*/ - case _ => arraycopy(src, srcPos, dest, destPos, length) - } - } else - arraycopy(src, srcPos, dest, destPos, length) - } - } - } - - /** Concatenate all argument sequences into a single array. - * - * @param xs the given argument sequences - * @return the array created from the concatenated arguments - */ - def concat[T](xs: Seq[T]*): Array[T] = { - var len = 0 - for (x <- xs) len += x.length - val result = new Array[T](len) - var start = 0 - for (x <- xs) { - copy(x.toArray, 0, result, start, x.length) - start += x.length - } - result - } - - /** Create an array with given elements. - * - * @param xs the elements to put in the array - * @return the array containing elements xs. - */ - def apply[A](xs: A*): Array[A] = { - val array = new Array[A](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } -/*!!! enable when arrays in Scala - def apply(xs: Boolean*): Array[Boolean] = { - val array = new Array[Boolean](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } - - def apply(xs: Byte*): Array[Byte] = { - val array = new Array[Byte](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } - - def apply(xs: Short*): Array[Short] = { - val array = new Array[Short](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } - - def apply(xs: Char*): Array[Char] = { - val array = new Array[Char](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } - - def apply(xs: Int*): Array[Int] = { - val array = new Array[Int](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } - - def apply(xs: Long*): Array[Long] = { - val array = new Array[Long](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } - - def apply(xs: Float*): Array[Float] = { - val array = new Array[Float](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } - - def apply(xs: Double*): Array[Double] = { - val array = new Array[Double](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } - - def apply(xs: Unit*): Array[Unit] = { - val array = new Array[Unit](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } -*/ - /** Create an array containing several copies of an element. - * - * @param n the length of the resulting array - * @param elem the element composing the resulting array - * @return an array composed of n elements all equal to elem - * @deprecated use `Array.fill` instead. - */ - @deprecated def make[A](n: Int, elem: A): Array[A] = { - val a = new Array[A](n) - var i = 0 - while (i < n) { - a(i) = elem - i += 1 - } - a - } - - /** Create an array containing the values of a given function <code>f</code> - * over given range <code>[0..n)</code> - * @deprecated use `Array.tabulate` instead. - */ - @deprecated def fromFunction[A](f: Int => A)(n: Int): Array[A] = { - val a = new Array[A](n) - var i = 0 - while (i < n) { - a(i) = f(i) - i += 1 - } - a - } - - /** Create an array containing the values of a given function <code>f</code> - * over given range <code>[0..n1, 0..n2)</code> - * @deprecated use `Array.tabulate` instead. - */ - @deprecated def fromFunction[A](f: (Int, Int) => A)(n1: Int, n2: Int): Array[Array[A]] = - fromFunction(i => fromFunction(f(i, _))(n2))(n1) - - /** Create an array containing the values of a given function <code>f</code> - * over given range <code>[0..n1, 0..n2, 0..n3)</code> - * @deprecated use `Array.tabulate` instead. - */ - @deprecated def fromFunction[A](f: (Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = - fromFunction(i => fromFunction(f(i, _, _))(n2, n3))(n1) - - /** Create an array containing the values of a given function <code>f</code> - * over given range <code>[0..n1, 0..n2, 0..n3, 0..n4)</code> - * @deprecated use `Array.tabulate` instead. - */ - @deprecated def fromFunction[A](f: (Int, Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = - fromFunction(i => fromFunction(f(i, _, _, _))(n2, n3, n4))(n1) - - /** Create an array containing the values of a given function <code>f</code> - * over given range <code>[0..n1, 0..n2, 0..n3, 0..n4, 0..n5)</code> - * @deprecated use `Array.tabulate` instead. - */ - @deprecated def fromFunction[A](f: (Int, Int, Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = - fromFunction(i => fromFunction(f(i, _, _, _, _))(n2, n3, n4, n5))(n1) - - /** Create array with given dimensions */ - def ofDim[A](n1: Int): Array[A] = - new Array[A](n1) - def ofDim[A](n1: Int, n2: Int): Array[Array[A]] = - tabulate(n1)(_ => ofDim[A](n2)) - def ofDim[A](n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = - tabulate(n1)(_ => ofDim[A](n2, n3)) - def ofDim[A](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = - tabulate(n1)(_ => ofDim[A](n2, n3, n4)) - def ofDim[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = - tabulate(n1)(_ => ofDim[A](n2, n3, n4, n5)) -} - -/** This class represents polymorphic arrays. <code>Array[T]</code> is Scala's representation - * for Java's <code>T[]</code>. - * - * @author Martin Odersky - * @version 1.0 - */ -final class Array[A](_length: Int) extends Vector[A] with MutableVectorTemplate[Array, A] { - - /** Multidimensional array creation - * @deprecated use Array.ofDim instead - */ - @deprecated def this(dim1: Int, dim2: Int) = { - this(dim1) - throw new Error() - } - - /** Multidimensional array creation - * @deprecated use Array.ofDim instead */ - @deprecated def this(dim1: Int, dim2: Int, dim3: Int) = { - this(dim1) - throw new Error() - } - - /** Multidimensional array creation - * @deprecated use Array.ofDim instead */ - @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int) = { - this(dim1) - throw new Error() - } - - /** Multidimensional array creation - * @deprecated use Array.ofDim instead */ - @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int) = { - this(dim1); - throw new Error() - } - - /** Multidimensional array creation - * @deprecated use Array.ofDim instead */ - @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int) = { - this(dim1) - throw new Error() - } - - /** Multidimensional array creation - * @deprecated use Array.ofDim instead */ - @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int) = { - this(dim1) - throw new Error() - } - - /** Multidimensional array creation - * @deprecated use Array.ofDim instead */ - @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int) = { - this(dim1) - throw new Error() - } - - /** Multidimensional array creation - * @deprecated use Array.ofDim instead */ - @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int, dim9: Int) = { - this(dim1) - throw new Error() - } - - /** The length of the array */ - def length: Int = throw new Error() - - /** The element at given index. - * <p> - * Indices start a <code>0</code>; <code>xs.apply(0)</code> is the first - * element of array <code>xs</code>. - * </p> - * <p> - * Note the indexing syntax <code>xs(i)</code> is a shorthand for - * <code>xs.apply(i)</code>. - * </p> - * - * @param i the index - * @throws ArrayIndexOutOfBoundsException if <code>i < 0</code> or - * <code>length <= i</code> - */ - def apply(i: Int): A = throw new Error() - - /* Create a new array builder */ - def newBuilder[B]: Builder[Array, B] = throw new Error() - - /** <p> - * Update the element at given index. - * </p> - * <p> - * Indices start a <code>0</code>; <code>xs.apply(0)</code> is the first - * element of array <code>xs</code>. - * </p> - * <p> - * Note the indexing syntax <code>xs(i) = x</code> is a shorthand - * for <code>xs.update(i, x)</code>. - * </p> - * - * @param i the index - * @param x the value to be written at index <code>i</code> - * @throws ArrayIndexOutOfBoundsException if <code>i < 0</code> or - * <code>length <= i</code> - */ - override def update(i: Int, x: A) { throw new Error() } - - /** - * @return a deep string representation of this array. - */ - def deepToString(): String = throw new Error() - - /** <p> - * Returns a string representation of this array object. The resulting string - * begins with the string <code>start</code> and is finished by the string - * <code>end</code>. Inside, the string representations of elements (w.r.t. - * the method <code>deepToString()</code>) are separated by the string - * <code>sep</code>. For example: - * </p> - * <p> - * <code>Array(Array(1, 2), Array(3)).deepMkString("[", "; ", "]") = "[[1; 2]; [3]]"</code> - * </p> - * - * @param start starting string. - * @param sep separator string. - * @param end ending string. - * @return a string representation of this array object. - */ - def deepMkString(start: String, sep: String, end: String): String = - throw new Error() - - /** Returns a string representation of this array object. The string - * representations of elements (w.r.t. the method <code>deepToString()</code>) - * are separated by the string <code>sep</code>. - * - * @param sep separator string. - * @return a string representation of this array object. - */ - def deepMkString(sep: String): String = throw new Error() - - /** <p> - * Returns <code>true</code> if the two specified arrays are - * <em>deeply equal</em> to one another. - * </p> - * <p> - * Two array references are considered deeply equal if both are null, - * or if they refer to arrays that contain the same number of elements - * and all corresponding pairs of elements in the two arrays are deeply - * equal. - * </p> - * <p> - * See also method <code>deepEquals</code> in the Java class - * <a href="http://java.sun.com/javase/6/docs/api/java/util/Arrays.html" - * target="_top">java.utils.Arrays</a> - * </p> - * - * @param that the second - * @return <code>true</code> iff both arrays are deeply equal. - */ - def deepEquals(that: Any): Boolean = throw new Error() - -} diff --git a/src/library/scalax/collection/mutable/ArrayBuffer.scala b/src/library/scalax/collection/mutable/ArrayBuffer.scala deleted file mode 100644 index 1692280e21..0000000000 --- a/src/library/scalax/collection/mutable/ArrayBuffer.scala +++ /dev/null @@ -1,140 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: ArrayBuffer.scala 15407 2008-06-20 09:26:36Z stepancheg $ - - -package scalax.collection.mutable - -import generic.{SequenceFactory, MutableVectorTemplate, Builder} - -/* Factory object for `ArrayBuffer` class */ -object ArrayBuffer extends SequenceFactory[ArrayBuffer] { - def apply[A](args: A*): ArrayBuffer[A] = new ArrayBuffer[A] ++ args.asInstanceOf[Iterable[A]] // !@! -} - -/** An implementation of the <code>Buffer</code> class using an array to - * represent the assembled sequence internally. Append, update and random - * access take constant time (amortized time). Prepends and removes are - * linear in the buffer size. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.8 - */ -@serializable -class ArrayBuffer[A](override protected val initialSize: Int) - extends Buffer[A] - with Vector[A] - with MutableVectorTemplate[ArrayBuffer, A] - with Builder[ArrayBuffer, A] - with ResizableArray[A] { - - def this() = this(16) - - def clear() { reduceToSize(0) } - - override def newBuilder[B]: Builder[ArrayBuffer, B] = new ArrayBuffer[B] - - /** Appends a single element to this buffer and returns - * the identity of the buffer. It takes constant time. - * - * @param elem the element to append. - */ - def +=(elem: A) { - ensureSize(size0 + 1) - array(size0) = elem.asInstanceOf[AnyRef] - size0 += 1 - } - - /** Appends a number of elements provided by an iterable object - * via its <code>elements</code> method. The identity of the - * buffer is returned. - * - * @param iter the iterfable object. - * @return the updated buffer. - */ - override def ++=(iter: collection.Iterable[A]) = iter match { - case v: Vector[_] => - val n = v.length - ensureSize(size0 + n) - v.copyToArray(array.asInstanceOf[scala.Array[Any]], n) - case _ => - super.++=(iter) - } - - /** Prepends a single element to this buffer and return - * the identity of the buffer. It takes time linear in - * the buffer size. - * - * @param elem the element to append. - * @return the updated buffer. - */ - def +:(elem: A): this.type = { - ensureSize(size0 + 1) - copy(0, 1, size0) - array(0) = elem.asInstanceOf[AnyRef] - size0 += 1 - this - } - - /** Prepends a number of elements provided by an iterable object - * via its <code>elements</code> method. The identity of the - * buffer is returned. - * - * @param iter the iterable object. - * @return the updated buffer. - */ - override def ++:(iter: Iterable[A]): this.type = { insertAll(0, iter); this } - - /** Inserts new elements at the index <code>n</code>. Opposed to method - * <code>update</code>, this method will not replace an element with a - * one. Instead, it will insert a new element at index <code>n</code>. - * - * @param n the index where a new element will be inserted. - * @param iter the iterable object providing all elements to insert. - * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds. - */ - def insertAll(n: Int, iter: Iterable[A]) { - if ((n < 0) || (n > size0)) - throw new IndexOutOfBoundsException(n.toString) - val xs = iter.elements.toList - val len = xs.length - ensureSize(size0 + len) - copy(n, n + len, size0 - n) - xs.copyToArray(array.asInstanceOf[scala.Array[Any]], n) - size0 += len - } - - /** Removes the element on a given index position. It takes time linear in - * the buffer size. - * - * @param n the index which refers to the first element to delete. - * @param count the number of elemenets to delete - * @return the updated array buffer. - * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds. - */ - def remove(n: Int, count: Int) { - if ((n < 0) || (n >= size0)) - throw new IndexOutOfBoundsException(n.toString) - copy(n + count, n, size0 - (n + count)) - size0 -= count - } - - /** Return a clone of this buffer. - * - * @return an <code>ArrayBuffer</code> with the same elements. - */ - override def clone(): Buffer[A] = new ArrayBuffer[A] ++ this - - def result: ArrayBuffer[A] = this - - /** Defines the prefix of the string representation. - */ - override def stringPrefix: String = "ArrayBuffer" -} diff --git a/src/library/scalax/collection/mutable/DefaultMapModel.scala b/src/library/scalax/collection/mutable/DefaultMapModel.scala deleted file mode 100644 index fda7798e26..0000000000 --- a/src/library/scalax/collection/mutable/DefaultMapModel.scala +++ /dev/null @@ -1,44 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: DefaultMapModel.scala 16893 2009-01-13 13:09:22Z cunei $ - - -package scalax.collection.mutable - -/** This class is used internally. It implements the mutable <code>Map</code> - * class in terms of three functions: <code>findEntry</code>, - * <code>addEntry</code>, and <code>entries</code>. - * - * @author Matthias Zenger - * @version 1.0, 08/07/2003 - */ -trait DefaultMapModel[A, B] extends Map[A, B] { - - type Entry = DefaultEntry[A, B] - - protected def findEntry(key: A): Entry - protected def addEntry(e: Entry) - protected def entries: Iterator[Entry] - - def get(key: A): Option[B] = { - val e = findEntry(key) - if (e == null) None - else Some(e.value); - } - - def update(key: A, value: B): this.type = { - val e = findEntry(key) - if (e == null) addEntry(new Entry(key, value)) - else e.value = value - this - } - - def elements = entries map {e => (e.key, e.value)} -} - diff --git a/src/library/scalax/collection/mutable/FlatHashTable.scala b/src/library/scalax/collection/mutable/FlatHashTable.scala deleted file mode 100644 index c8fe2cede3..0000000000 --- a/src/library/scalax/collection/mutable/FlatHashTable.scala +++ /dev/null @@ -1,164 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: FlatHashTable.scala 16893 2009-01-13 13:09:22Z cunei $ - -package scalax.collection.mutable - -trait FlatHashTable[A] { - - /** The load factor for the hash table; must be < 500 (0.5) - */ - protected def loadFactor: Int = 450 - protected final def loadFactorDenum = 1000 - - /** The initial size of the hash table. - */ - protected def initialSize: Int = 16 - - private final val tableDebug = false - - /** The actual hash table. - */ - protected var table: scala.Array[AnyRef] = - if (initialSize == 0) null else new scala.Array(initialSize) - - /** The number of mappings contained in this hash table. - */ - protected var tableSize = 0 - - /** The next size value at which to resize (capacity * load factor). - */ - protected var threshold: Int = newThreshold(initialSize) - - /** Returns the number of entires in this hash table. - */ - def size: Int = tableSize - - def findEntry(elem: A): Option[A] = { - var h = index(elemHashCode(elem)) - var entry = table(h) - while (null != entry && entry != elem) { - h = (h + 1) % table.length - entry = table(h) - } - if (null == entry) None else Some(entry.asInstanceOf[A]) - } - - def containsEntry(elem: A): Boolean = { - var h = index(elemHashCode(elem)) - var entry = table(h) - while (null != entry && entry != elem) { - h = (h + 1) % table.length - entry = table(h) - } - null != entry - } - - def addEntry(elem: A) : Boolean = { - var h = index(elemHashCode(elem)) - var entry = table(h) - while (null != entry) { - if (entry == elem) return false - h = (h + 1) % table.length - entry = table(h) - } - table(h) = elem.asInstanceOf[AnyRef] - tableSize = tableSize + 1 - if (tableSize >= threshold) growTable() - true - } - - def removeEntry(elem: A) : Option[A] = { - if (tableDebug) checkConsistent() - def precedes(i: Int, j: Int) = { - val d = table.length >> 1 - if (i <= j) j - i < d - else i - j > d - } - var h = index(elemHashCode(elem)) - var entry = table(h) - while (null != entry) { - if (entry == elem) { - var h0 = h - var h1 = (h0 + 1) % table.length - while (null != table(h1)) { - val h2 = index(elemHashCode(table(h1).asInstanceOf[A])) - //Console.println("shift at "+h1+":"+table(h1)+" with h2 = "+h2+"? "+(h2 != h1)+precedes(h2, h0)+table.length) - if (h2 != h1 && precedes(h2, h0)) { - //Console.println("shift "+h1+" to "+h0+"!") - table(h0) = table(h1) - h0 = h1 - } - h1 = (h1 + 1) % table.length - } - table(h0) = null - tableSize -= 1 - if (tableDebug) checkConsistent() - return Some(entry.asInstanceOf[A]) - } - h = (h + 1) % table.length - entry = table(h) - } - None - } - - def elements = new Iterator[A] { - private var i = 0 - def hasNext: Boolean = { - while (i < table.length && (null == table(i))) i += 1; - i < table.length - } - def next(): A = - if (hasNext) { i += 1; table(i - 1).asInstanceOf[A] } - else Iterator.empty.next - } - - private def growTable() { - val oldtable = table - table = new scala.Array[AnyRef](table.length * 2) - tableSize = 0 - threshold = newThreshold(table.length) - var i = 0 - while (i < oldtable.length) { - val entry = oldtable(i) - if (null != entry) addEntry(entry.asInstanceOf[A]) - i += 1 - } - if (tableDebug) checkConsistent() - } - - private def checkConsistent() { - for (i <- 0 until table.length) - if (table(i) != null && !containsEntry(table(i).asInstanceOf[A])) - assert(false, i+" "+table(i)+" "+table.toString) - } - - protected def elemHashCode(elem: A) = elem.hashCode() - - protected final def improve(hcode: Int) = { - var h: Int = hcode + ~(hcode << 9) - h = h ^ (h >>> 14) - h = h + (h << 4) - h ^ (h >>> 10) - } - - protected final def index(hcode: Int) = improve(hcode) & (table.length - 1) - - private def newThreshold(size: Int) = { - val lf = loadFactor - assert(lf < (loadFactorDenum / 2), "loadFactor too large; must be < 0.5") - (size.toLong * lf / loadFactorDenum ).toInt - } - - protected def clear() { - var i = table.length - 1 - while (i >= 0) { table(i) = null; i -= 1 } - tableSize = 0 - } -} diff --git a/src/library/scalax/collection/mutable/HashMap.scala b/src/library/scalax/collection/mutable/HashMap.scala deleted file mode 100644 index 4d3342636c..0000000000 --- a/src/library/scalax/collection/mutable/HashMap.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: HashMap.scala 16893 2009-01-13 13:09:22Z cunei $ - - -package scalax.collection.mutable - -import generic._ - -/** This class implements mutable maps using a hashtable. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.8 - */ -object HashMap extends MapFactory[HashMap] { - - /** The empty map of this type */ - def empty[A, B] = new HashMap[A, B] - -} - -@serializable -class HashMap[A, B] - extends Map[A, B] - with MapTemplate[A, B, HashMap] - with HashTable[A] - with DefaultMapModel[A, B] { - - def empty[B] = HashMap.empty[A, B] - - def -= (key: A) { removeEntry(key) } - - override def clear() = super.clear() - - override def clone(): Map[A, B] = new HashMap[A, B] ++ this -} diff --git a/src/library/scalax/collection/mutable/HashSet.scala b/src/library/scalax/collection/mutable/HashSet.scala deleted file mode 100644 index 601d0885c0..0000000000 --- a/src/library/scalax/collection/mutable/HashSet.scala +++ /dev/null @@ -1,48 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: HashSet.scala 16893 2009-01-13 13:09:22Z cunei $ - - -package scalax.collection.mutable - -import generic.{SetTemplate, SetFactory, AddableBuilder} - -/** Factory object for `HashSet` class */ -object HashSet extends SetFactory[HashSet] { - /** The empty set of this type */ - def empty[A] = new HashSet[A] -} - -/** This class implements mutable sets using a hashtable. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.0, 31/12/2006 - */ -@serializable -class HashSet[A] - extends Set[A] - with SetTemplate[HashSet, A] - with FlatHashTable[A] { - - def contains(elem: A): Boolean = containsEntry(elem) - - def +=(elem: A) { addEntry(elem) } - - def -=(elem: A) { removeEntry(elem) } - - override def clear() = super.clear() - - override def newBuilder[B]: generic.Builder[HashSet, B] = - new AddableBuilder[HashSet, B](HashSet.empty) - - override def clone(): HashSet[A] = new HashSet[A] ++ this -} - - diff --git a/src/library/scalax/collection/mutable/HashTable.scala b/src/library/scalax/collection/mutable/HashTable.scala deleted file mode 100644 index 73ff61f3df..0000000000 --- a/src/library/scalax/collection/mutable/HashTable.scala +++ /dev/null @@ -1,172 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: HashTable.scala 16884 2009-01-09 16:52:09Z cunei $ - - -package scalax.collection.mutable - -/** This class can be used to construct data structures that are based - * on hashtables. Class <code>HashTable[A]</code> implements a hashtable - * that maps keys of type <code>A</code> to values of the fully abstract - * member type <code>Entry</code>. Classes that make use of <code>HashTable</code> - * have to provide an implementation for <code>Entry</code> - * - * There are mainly two parameters that affect the performance of a hashtable: - * the <i>initial size</i> and the <i>load factor</i>. The <i>size</i> - * refers to the number of <i>buckets</i> in the hashtable, and the <i>load - * factor</i> is a measure of how full the hashtable is allowed to get before - * its size is automatically doubled. Both parameters may be changed by - * overriding the corresponding values in class <code>HashTable</code>. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.0, 31/12/2006 - */ -trait HashTable[A] extends AnyRef { - - protected type Entry >: Null <: HashEntry[A, Entry] - - /** The load factor for the hash table (in 0.001 step). - */ - protected def loadFactor: Int = 750 // corresponds to 75% - protected final val loadFactorDenum = 1000; - - /** The initial size of the hash table. - */ - protected def initialSize: Int = 16 - - /** The initial threshold - */ - protected def initialThreshold: Int = newThreshold(initialSize) - - /** The actual hash table. - */ - protected var table: scala.Array[HashEntry[A, Entry]] = - if (initialSize == 0) null else new scala.Array(initialSize) - - /** The number of mappings contained in this hash table. - */ - protected var tableSize: Int = 0 - - /** The next size value at which to resize (capacity * load factor). - */ - protected var threshold: Int = initialThreshold - - /** Returns the size of this hash table. - */ - def size = tableSize - - protected def findEntry(key: A): Entry = { - val h = index(elemHashCode(key)) - var e = table(h).asInstanceOf[Entry] - while (e != null && !elemEquals(e.key, key)) e = e.next - e - } - - protected def addEntry(e: Entry) { - val h = index(elemHashCode(e.key)) - e.next = table(h).asInstanceOf[Entry] - table(h) = e - tableSize = tableSize + 1 - if (tableSize > threshold) - resize(2 * table.length) - } - - protected def removeEntry(key: A) : Option[Entry] = { - val h = index(elemHashCode(key)) - var e = table(h).asInstanceOf[Entry] - if (e != null) { - if (elemEquals(e.key, key)) { - table(h) = e.next - tableSize = tableSize - 1 - return Some(e) - } else { - var e1 = e.next - while (e1 != null && !elemEquals(e1.key, key)) { - e = e1 - e1 = e1.next - } - if (e1 != null) { - e.next = e1.next - tableSize = tableSize - 1 - return Some(e1) - } - } - } - None - } - - protected def entries: Iterator[Entry] = new Iterator[Entry] { - val iterTable = table - var idx = table.length - 1 - var es = iterTable(idx).asInstanceOf[Entry] - scan() - def hasNext = es != null - def next = { - val res = es - es = es.next - scan() - res - } - def scan() { - while (es == null && idx > 0) { - idx = idx - 1 - es = iterTable(idx).asInstanceOf[Entry] - } - } - } - - def clear() { - var i = table.length - 1 - while (i >= 0) { table(i) = null; i = i - 1 } - tableSize = 0 - } - - private def newThreshold(size: Int) = - ((size.toLong * loadFactor)/loadFactorDenum).toInt - - private def resize(newSize: Int) = { - val oldTable = table - table = new scala.Array(newSize) - var i = oldTable.length - 1 - while (i >= 0) { - var e = oldTable(i) - while (e != null) { - val h = index(elemHashCode(e.key)) - val e1 = e.next - e.next = table(h).asInstanceOf[Entry] - table(h) = e - e = e1 - } - i = i - 1 - } - threshold = newThreshold(newSize) - } - - protected def elemEquals(key1: A, key2: A): Boolean = (key1 == key2) - - protected def elemHashCode(key: A) = key.hashCode() - - protected final def improve(hcode: Int) = { - var h: Int = hcode + ~(hcode << 9) - h = h ^ (h >>> 14) - h = h + (h << 4) - h ^ (h >>> 10) - } - - protected final def index(hcode: Int) = improve(hcode) & (table.length - 1) -} - -trait HashEntry[A, E] { - val key: A - var next: E = _ -} - - - diff --git a/src/library/scalax/collection/mutable/Iterable.scala b/src/library/scalax/collection/mutable/Iterable.scala deleted file mode 100755 index 0872c3c549..0000000000 --- a/src/library/scalax/collection/mutable/Iterable.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - -package scalax.collection.mutable - -import generic._ - -/** Collection classes mixing in this class provide a method - * <code>elements</code> which returns an iterator over all the - * elements contained in the collection. - * - * @note If a collection has a known <code>size</code>, it should also sub-type <code>SizedIterable</code>. - * - * @author Matthias Zenger - * @autor Martin Odersky - * @owner Martin Odersky - * @version 2.8 - */ -trait Iterable[A] extends collection.Iterable[A] with IterableTemplate[Iterable, A] - -/* Factory object for `Iterable` class */ -object Iterable extends IterableFactory[Iterable] { - /** The empty iterable */ - def apply[A](args: A*): Iterable[A] = ArrayBuffer.apply(args: _*) // !!! swicth to Array? -} diff --git a/src/library/scalax/collection/mutable/ListBuffer.scala b/src/library/scalax/collection/mutable/ListBuffer.scala deleted file mode 100644 index faf897aef2..0000000000 --- a/src/library/scalax/collection/mutable/ListBuffer.scala +++ /dev/null @@ -1,314 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ - - -package scalax.collection.mutable - -import generic._ -import immutable.List -import collection.immutable.{List, Nil, ::} - -/* Factory object for `ListBuffer` class */ -object ListBuffer extends SequenceFactory[ListBuffer] { - def apply[A](args: A*): ListBuffer[A] = new ListBuffer[A] -} - -/** A Buffer implementation back up by a list. It provides constant time - * prepend and append. Most other operations are linear. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.8 - */ -@serializable -final class ListBuffer[A] - extends Buffer[A] - with SequenceTemplate[ListBuffer, A] - with Addable[ListBuffer[A], A] - with Subtractable[ListBuffer[A], A] - with Builder[List, A] - with SequenceForwarder[A] -{ - import collection.immutable.Sequence - - private var start: List[A] = Nil - private var last0: ::[A] = _ - private var exported: Boolean = false - private var len = 0 - - protected def underlying: Sequence[A] = start - - override def newBuilder[B]: Builder[ListBuffer, B] = - new AddableBuilder[ListBuffer, B](new ListBuffer[B]) // !!! Adriaan: inference failure here - - /** The current length of the buffer - */ - override def length = len - - // Implementations of abstract methods in Buffer - - /** Replaces element at index <code>n</code> with the new element - * <code>newelem</code>. Takes time linear in the buffer size. (except the first - * element, which is updated in constant time). - * - * @param n the index of the element to replace. - * @param x the new element. - * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds. - */ - def update(n: Int, x: A) { - try { - if (exported) copy() - if (n == 0) { - val newElem = new :: (x, start.tail); - if (last0 eq start) { - last0 = newElem - len += 1 - } - start = newElem - } else { - var cursor = start - var i = 1 - while (i < n) { - cursor = cursor.tail - i += 1 - } - val newElem = new :: (x, cursor.tail.tail) - if (last0 eq cursor.tail) { - last0 = newElem - len += 1 - } - cursor.asInstanceOf[::[A]].tl = newElem - } - } catch { - case ex: Exception => throw new IndexOutOfBoundsException(n.toString()) - } - } - - /** Appends a single element to this buffer. This operation takes constant time. - * - * @param x the element to append. - */ - def += (x: A) { - if (exported) copy() - if (start.isEmpty) { - last0 = new :: (x, Nil) - start = last0 - } else { - val last1 = last0 - last0 = new :: (x, Nil) - last1.tl = last0 - } - len += 1 - } - - /** Clears the buffer contents. - */ - def clear() { - start = Nil - exported = false - len = 0 - } - - /** Prepends a single element to this buffer. This operation takes constant - * time. - * - * @param x the element to prepend. - * @return this buffer. - */ - def +: (x: A): this.type = { - if (exported) copy() - val newElem = new :: (x, start) - if (start.isEmpty) last0 = newElem - start = newElem - len += 1 - this - } - - /** Inserts new elements at the index <code>n</code>. Opposed to method - * <code>update</code>, this method will not replace an element with a new - * one. Instead, it will insert a new element at index <code>n</code>. - * - * @param n the index where a new element will be inserted. - * @param iter the iterable object providing all elements to insert. - * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds. - */ - def insertAll(n: Int, iter: Iterable[A]) { - try { - if (exported) copy() - var elems = iter.elements.toList.reverse - len += elems.length - if (n == 0) { - while (!elems.isEmpty) { - val newElem = new :: (elems.head, start) - if (start.isEmpty) last0 = newElem - start = newElem - elems = elems.tail - } - } else { - var cursor = start - var i = 1 - while (i < n) { - cursor = cursor.tail - i += 1 - } - while (!elems.isEmpty) { - val newElem = new :: (elems.head, cursor.tail) - if (cursor.tail.isEmpty) last0 = newElem - cursor.asInstanceOf[::[A]].tl = newElem - elems = elems.tail - } - } - } catch { - case ex: Exception => - throw new IndexOutOfBoundsException(n.toString()) - } - } - - /** Removes a given number of elements on a given index position. May take time linear in - * the buffer size. - * - * @param n the index which refers to the first element to remove. - * @param count the number of elements to remove. - */ - def remove(n: Int, count: Int) { - if (exported) copy() - val n1 = n max 0 - val count1 = count min (len - n1) - var old = start.head; - if (n1 == 0) { - var c = count1 - while (c > 0) { - start = start.tail - c -= 1 - } - } else { - var cursor = start - var i = 1 - while (i < n1) { - cursor = cursor.tail - i += 1 - } - var c = count1 - while (c > 0) { - if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]] - cursor.asInstanceOf[::[A]].tl = cursor.tail.tail - c -= 1 - } - } - len -= count1 - } - -// Implementation of abstract method in Builder - - def result = toList - - /** Converts this buffer to a list. Takes constant time. The buffer is - * copied lazily, the first time it is mutated. - */ - override def toList: List[A] = { - exported = !start.isEmpty - start - } - -// New methods in ListBuffer - - /** Prepends the elements of this buffer to a given list - * - * @param xs the list to which elements are prepended - */ - def prependToList(xs: List[A]): List[A] = - if (start.isEmpty) xs - else { last0.tl = xs; toList } - -// Overrides of methods in Buffer - - /** Removes the element on a given index position. May take time linear in - * the buffer size - * - * @param n the index which refers to the element to delete. - * @return n the element that was formerly at position <code>n</code>. - * @pre an element exists at position <code>n</code> - * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds. - */ - override def remove(n: Int): A = try { - if (n < 0 || n >= len) throw new IndexOutOfBoundsException(n.toString()) - if (exported) copy() - var old = start.head; - if (n == 0) { - start = start.tail - } else { - var cursor = start - var i = 1 - while (i < n) { - cursor = cursor.tail - i += 1 - } - old = cursor.tail.head - if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]] - cursor.asInstanceOf[::[A]].tl = cursor.tail.tail - } - len -= 1 - old - } - - /** Remove a single element from this buffer. May take time linear in the buffer size. - * - * @param x the element to remove. - */ - override def -= (elem: A) { - if (exported) copy() - if (start.isEmpty) {} - else if (start.head == elem) { - start = start.tail - len -= 1 - } else { - var cursor = start - while (!cursor.tail.isEmpty && cursor.tail.head != elem) { - cursor = cursor.tail - } - if (!cursor.tail.isEmpty) { - val z = cursor.asInstanceOf[::[A]] - if (z.tl == last0) - last0 = z - z.tl = cursor.tail.tail - len -= 1 - } - } - } - - /** expose the underlying list but do not mark it as exported */ - def readOnly: List[A] = start - - // Private methods - - /** Copy contents of this buffer */ - private def copy() { - var cursor = start - val limit = last0.tail - clear - while (cursor ne limit) { - this += cursor.head - cursor = cursor.tail - } - } - - /** Returns a clone of this buffer. - * - * @return a <code>ListBuffer</code> with the same elements. - */ - override def clone(): Buffer[A] = (new ListBuffer[A]) ++ this - - /** Defines the prefix of the string representation. - * - * @return the string representation of this buffer. - */ - override def stringPrefix: String = "ListBuffer" -} - diff --git a/src/library/scalax/collection/mutable/Map.scala b/src/library/scalax/collection/mutable/Map.scala deleted file mode 100755 index 82fb6a5680..0000000000 --- a/src/library/scalax/collection/mutable/Map.scala +++ /dev/null @@ -1,73 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Map.scala 16884 2009-01-09 16:52:09Z cunei $ - - -package scalax.collection.mutable - -import generic._ - -/* Factory object for `Map` class */ -object Map extends MapFactory[Map] { - def empty[A, B]: Map[A, B] = new HashMap[A, B] -} - -trait Map[A, B] - extends collection.Map[A, B] - with MapTemplate[A, B, Map] - with Growable[(A, B)] - with Shrinkable[A] - with Cloneable[Map[A, B]] { -self => - - /** This method allows one to add a new mapping from <code>key</code> - * to <code>value</code> to the map. If the map already contains a - * mapping for <code>key</code>, it will be overridden by this - * function. - * - * @param key The key to update - * @param value The new value - */ - def update(key: A, value: B): this.type - - /** Add a key/value pair to this map. - * @param kv the key/value pair. - */ - def += (kv: (A, B)) { update(kv._1, kv._2) } - - /** Remove a key from this map, noop if key is not present. - * @param key the key to be removed - */ - def -= (key: A) - - def -(key: A): this.type = { -=(key); this } - - /** Removes all elements from the set for - * which the predicate <code>p</code> yields the value <code>false</code>. - */ - def retain(p: A => Boolean): Unit = for ((k, v) <- this) if (!p(k)) -=(k) - - /** Removes all elements from the set. After this operation is completed, - * the set will be empty. - */ - def clear() { for ((k, v) <- elements) -=(k) } - - override def clone(): Map[A, B] = empty[B] ++ this - - /** Return a read-only projection of this set !!! just us an (immutable) setProxy? */ - def readOnly : collection.Map[A, B] = new collection.Map[A, B] { - override def size = self.size - override def update(key: A, value: B) = self.update(key, value) - override def - (elem: A) = self - elem - override def elements = self.elements - override def foreach(f: ((A, B)) => Unit) = self.foreach(f) - override def empty[C] = self.empty[C] - def get(key: A) = self.get(key) - } -} diff --git a/src/library/scalax/collection/mutable/OrderedIterable.scala b/src/library/scalax/collection/mutable/OrderedIterable.scala deleted file mode 100755 index 90ef8018c7..0000000000 --- a/src/library/scalax/collection/mutable/OrderedIterable.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - -package scalax.collection.mutable - -import generic._ - -trait OrderedIterable[A] extends Iterable[A] with collection.OrderedIterable[A] with OrderedIterableTemplate[OrderedIterable, A] - -/* Factory object for `OrderedIterable` class */ -object OrderedIterable extends IterableFactory[OrderedIterable] { - /** The empty iterable */ - def apply[A](args: A*): OrderedIterable[A] = ArrayBuffer.apply(args: _*) // !!! swicth to Array? -} - diff --git a/src/library/scalax/collection/mutable/ResizableArray.scala b/src/library/scalax/collection/mutable/ResizableArray.scala deleted file mode 100644 index 11c3659712..0000000000 --- a/src/library/scalax/collection/mutable/ResizableArray.scala +++ /dev/null @@ -1,108 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: ResizableArray.scala 15407 2008-06-20 09:26:36Z stepancheg $ - - -package scalax.collection.mutable - -/** This class is used internally to implement data structures that - * are based on resizable arrays. - * - * @author Matthias Zenger, Burak Emir - * @version 1.0, 03/05/2004 - */ -trait ResizableArray[A] extends Vector[A] { - - import scala.Array // !!! - - protected def initialSize: Int = 16 - protected var array: Array[AnyRef] = new Array[AnyRef](initialSize min 1) - - protected var size0: Int = 0 - - //########################################################################## - // implement/override methods of Vector[A] - - /** Returns the length of this resizable array. - */ - def length: Int = size0 - - def apply(idx: Int) = { - if (idx >= size0) throw new IndexOutOfBoundsException(idx.toString) - array(idx).asInstanceOf[A] - } - - def update(idx: Int, elem: A) { - if (idx >= size0) throw new IndexOutOfBoundsException(idx.toString) - array(idx) = elem.asInstanceOf[AnyRef] - } - - /** Fills the given array <code>xs</code> with the elements of - * this sequence starting at position <code>start</code>. - * - * @param xs the array to fill. - * @param start starting index. - */ - override def copyToArray[B >: A](xs: Array[B], start: Int) { - Array.copy(array, 0, xs, start, size0) - } - - /** Copy all elements to a buffer - * @param The buffer to which elements are copied - */ - override def copyToBuffer[B >: A](dest: Buffer[B]) { - dest ++= array.asInstanceOf[Iterable[A]] // !@! - } - - override def foreach(f: A => Unit) { - var i = 0 - while (i < size) { - f(array(i).asInstanceOf[A]) - i += 1 - } - } - - //########################################################################## - - /** remove elements of this array at indices after <code>sz</code> - */ - def reduceToSize(sz: Int) { - require(sz <= size0) - while (size0 > sz) { - size0 -= 1 - array(size0) = null - } - } - - /** ensure that the internal array has at n cells */ - protected def ensureSize(n: Int) { - if (n > array.length) { - var newsize = array.length * 2 - while (n > newsize) - newsize = newsize * 2 - val newar: Array[AnyRef] = new Array(newsize) - Array.copy(array, 0, newar, 0, size0) - array = newar - } - } - - /** Swap two elements of this array. - */ - protected def swap(a: Int, b: Int) { - val h = array(a) - array(a) = array(b) - array(b) = h - } - - /** Move parts of the array. - */ - protected def copy(m: Int, n: Int, len: Int) { - Array.copy(array, m, array, n, len) - } -} diff --git a/src/library/scalax/collection/mutable/Sequence.scala b/src/library/scalax/collection/mutable/Sequence.scala deleted file mode 100755 index c4d72231d5..0000000000 --- a/src/library/scalax/collection/mutable/Sequence.scala +++ /dev/null @@ -1,23 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ - -package scalax.collection.mutable - -import generic._ - -trait Sequence[A] extends OrderedIterable[A] with collection.Sequence[A] with SequenceTemplate[Sequence, A] - -/* Factory object for `Sequence` class */ -object Sequence extends SequenceFactory[Sequence] { - /** The empty sequence */ - def apply[A](args: A*): Sequence[A] = ArrayBuffer.apply(args: _*) // !!! swicth to Array? -} - - diff --git a/src/library/scalax/collection/mutable/Set.scala b/src/library/scalax/collection/mutable/Set.scala deleted file mode 100644 index 78f3234336..0000000000 --- a/src/library/scalax/collection/mutable/Set.scala +++ /dev/null @@ -1,119 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Set.scala 16893 2009-01-13 13:09:22Z cunei $ - - -package scalax.collection.mutable - -import collection.generic._ - -/** The canonical factory methods for <a href="Set.html">mutable sets</a>. - * Currently these return <a href="HashSet.html">HashSet's</a>. - */ -object Set extends generic.SetFactory[Set] { - /** The empty map of this type; this is implemented as a hashtable */ - def empty[A]: Set[A] = new HashSet[A] -} - -/** This class represents mutable sets. Concrete set implementations - * just have to provide functionality for the abstract methods in - * <a href="../Set.html" target="contentFrame"> - * <code>scala.collection.Set</code></a> as well as for <code>+=</code>, - * <code>-= and <code>clear</code>. - * - * @author Matthias Zenger - * @author Martin Odersky - * @version 2.8 - */ -trait Set[A] extends collection.Set[A] - with SetTemplate[Set, A] - with Addable[Set[A], A] - with Subtractable[Set[A], A] - with Growable[A] - with Shrinkable[A] - with Cloneable[Set[A]] { -self => - - /** This method allows one to add or remove an element <code>elem</code> - * from this set depending on the value of parameter <code>included</code>. - * Typically, one would use the following syntax: - * <pre>set(elem) = true</pre> - * - */ - def update(elem: A, included: Boolean) { - if (included) this += elem else this -= elem - } - - /** Adds a new element to the set. - * - * @param elem the element to be added - */ - def +=(elem: A) - - /** Removes a single element from a set. - * @param elem The element to be removed. - */ - def -=(elem: A) - - /** Adds a new element to the set and returns the set itself. - * - * @param elem the element to be added - */ - def +(elem: A): this.type = { +=(elem); this } - - /** Removed a new element from the set and returns the set itself. - * - * @param elem the element to be added - */ - def -(elem: A): this.type = { -=(elem); this } - - /** This method computes an intersection with set <code>that</code>. - * It removes all the elements that are not present in <code>that</code>. - * - * @param that the set to intersect with. - */ - def intersect(that: Set[A]) { retain(that.contains) } - - /** Method <code>retain removes all elements from the set for - * which the predicate <code>p</code> yields the value <code>false</code>. - */ - def retain(p: A => Boolean): Unit = foreach (elem => if (!p(elem)) -=(elem)) - - /** Removes all elements from the set. After this operation is completed, - * the set will be empty. - */ - def clear() { foreach(-=) } - - override def clone(): Set[A] = { val b = newBuilder[A]; b ++= this; b.result } - - /** Send a message to this scriptable object. - * - * @param cmd the message to send. - * @throws <code>Predef.UnsupportedOperationException</code> - * if the message was not understood. - def <<(cmd: Message[A]): Unit = cmd match { - case Include(elem) => this += elem - case Remove(elem) => this -= elem - case Reset() => clear - case s: Script[_] => s.elements foreach << - case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") - } - */ - - /** Return a read-only projection of this set !!! just us an (immutable) setProxy? */ - def readOnly : collection.Set[A] = new collection.Set[A] { - def contains(item : A) = Set.this.contains(item) - override def size = self.size - override def +(elem: A) = self + elem - override def -(elem: A) = self - elem - override def elements = self.elements - override def foreach(f: A => Unit) = self.foreach(f) - override def newBuilder[B]: Builder[collection.Set, B] = self.newBuilder[B] - } -} diff --git a/src/library/scalax/collection/mutable/Vector.scala b/src/library/scalax/collection/mutable/Vector.scala deleted file mode 100644 index 1813172fbf..0000000000 --- a/src/library/scalax/collection/mutable/Vector.scala +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $ - -package scalax.collection.mutable - -import generic._ - -trait Vector[A] extends Sequence[A] with collection.Vector[A] with MutableVectorTemplate[Vector, A] - -/* Factory object for `Vector` class */ -object Vector extends SequenceFactory[Vector] { - /** The empty vector */ - def apply[A](args: A*): Vector[A] = ArrayBuffer.apply(args: _*) // !!! swicth to Array? -} diff --git a/src/library/scalax/runtime/BoxedAnyArray.scala b/src/library/scalax/runtime/BoxedAnyArray.scala deleted file mode 100755 index 6e14cafdfc..0000000000 --- a/src/library/scalax/runtime/BoxedAnyArray.scala +++ /dev/null @@ -1,239 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: BoxedAnyArray.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -import compat.Platform - -/** - * Arrays created by <code>new Array[T](length)</code> where <code>T</code> - * is a type variable. - * - * @author Martin Odersky - */ -@serializable -final class BoxedAnyArray[A](val length: Int) extends BoxedArray[A] { - - private var boxed = new Array[AnyRef](length) - private val hash = boxed.hashCode() - private var unboxed: AnyRef = null - private var elemClass: Class[_] = null - - def apply(index: Int): A = synchronized { - if (unboxed eq null) - boxed(index) - else if (elemClass eq classOf[Int]) - Int.box(unboxed.asInstanceOf[Array[Int]](index)) - else if (elemClass eq classOf[Double]) - Double.box(unboxed.asInstanceOf[Array[Double]](index)) - else if (elemClass eq classOf[Float]) - Float.box(unboxed.asInstanceOf[Array[Float]](index)) - else if (elemClass eq classOf[Long]) - Long.box(unboxed.asInstanceOf[Array[Long]](index)) - else if (elemClass eq classOf[Char]) - Char.box(unboxed.asInstanceOf[Array[Char]](index)) - else if (elemClass eq classOf[Byte]) - Byte.box(unboxed.asInstanceOf[Array[Byte]](index)) - else if (elemClass eq classOf[Short]) - Short.box(unboxed.asInstanceOf[Array[Short]](index)) - else if (elemClass eq classOf[Boolean]) - Boolean.box(unboxed.asInstanceOf[Array[Boolean]](index)) - else - unboxed.asInstanceOf[Array[AnyRef]](index) - }.asInstanceOf[A] - - def update(index: Int, _elem: A): Unit = synchronized { - val elem = _elem.asInstanceOf[AnyRef] - if (unboxed eq null) - boxed(index) = elem - else if (elemClass eq classOf[Int]) - unboxed.asInstanceOf[Array[Int]](index) = Int.unbox(elem) - else if (elemClass eq classOf[Double]) - unboxed.asInstanceOf[Array[Double]](index) = Double.unbox(elem) - else if (elemClass eq classOf[Float]) - unboxed.asInstanceOf[Array[Float]](index) = Float.unbox(elem) - else if (elemClass eq classOf[Long]) - unboxed.asInstanceOf[Array[Long]](index) = Long.unbox(elem) - else if (elemClass eq classOf[Char]) - unboxed.asInstanceOf[Array[Char]](index) = Char.unbox(elem) - else if (elemClass eq classOf[Byte]) - unboxed.asInstanceOf[Array[Byte]](index) = Byte.unbox(elem) - else if (elemClass eq classOf[Short]) - unboxed.asInstanceOf[Array[Short]](index) = Short.unbox(elem) - else if (elemClass eq classOf[Boolean]) - unboxed.asInstanceOf[Array[Boolean]](index) = Boolean.unbox(elem) - else - unboxed.asInstanceOf[Array[AnyRef]](index) = elem - } - - def unbox(elemClass: Class[_]): AnyRef = synchronized { - if (unboxed eq null) { - this.elemClass = elemClass; - if (elemClass eq classOf[Int]) { - val newvalue = new Array[Int](length) - var i = 0 - while (i < length) { - newvalue(i) = Int.unbox(boxed(i)) - i += 1 - } - unboxed = newvalue - } else if (elemClass eq classOf[Double]) { - val newvalue = new Array[Double](length) - var i = 0 - while (i < length) { - newvalue(i) = Double.unbox(boxed(i)) - i += 1 - } - unboxed = newvalue; - } else if (elemClass eq classOf[Float]) { - val newvalue = new Array[Float](length) - var i = 0 - while (i < length) { - newvalue(i) = Float.unbox(boxed(i)) - i += 1 - } - unboxed = newvalue; - } else if (elemClass eq classOf[Long]) { - val newvalue = new Array[Long](length) - var i = 0 - while (i < length) { - newvalue(i) = Long.unbox(boxed(i)) - i += 1 - } - unboxed = newvalue; - } else if (elemClass eq classOf[Char]) { - val newvalue = new Array[Char](length) - var i = 0 - while (i < length) { - newvalue(i) = Char.unbox(boxed(i)) - i += 1 - } - unboxed = newvalue - } else if (elemClass eq classOf[Byte]) { - val newvalue = new Array[Byte](length) - var i = 0 - while (i < length) { - newvalue(i) = Byte.unbox(boxed(i)) - i += 1 - } - unboxed = newvalue; - } else if (elemClass eq classOf[Short]) { - val newvalue = new Array[Short](length) - var i = 0 - while (i < length) { - newvalue(i) = Short.unbox(boxed(i)) - i += 1 - } - unboxed = newvalue; - } else if (elemClass eq classOf[Boolean]) { - val newvalue = new Array[Boolean](length) - var i = 0 - while (i < length) { - newvalue(i) = Boolean.unbox(boxed(i)) - i += 1 - } - unboxed = newvalue; - } else if (elemClass == classOf[AnyRef]) { - unboxed = boxed - } else { - unboxed = Platform.createArray(elemClass, length) - if (elemClass.isArray) { - var i = 0 - while (i < length) { - boxed(i) match { - case ba: BoxedArray[_] => boxed(i) = ba.unbox(elemClass.getComponentType()) - case _ => - } - i += 1 - } - } - Platform.arraycopy(boxed, 0, unboxed, 0, length) - } - boxed = null - } - unboxed - } - - override def equals(other: Any): Boolean = - other.isInstanceOf[BoxedAnyArray[_]] && (this eq (other.asInstanceOf[BoxedAnyArray[_]])) || - (if (unboxed eq null) boxed == other else unboxed == other) - - override def hashCode(): Int = hash - - def value: AnyRef = { - if (unboxed eq null) throw new NotDefinedError("BoxedAnyArray.value") - unboxed - } - - private def adapt(other: AnyRef): AnyRef = - if (this.unboxed eq null) - other match { - case that: BoxedAnyArray[_] => - if (that.unboxed eq null) { - that.boxed - } else { - if (ScalaRunTime.isValueClass(that.elemClass)) unbox(that.elemClass); - that.unboxed - } - case that: BoxedArray[_] => - adapt(that.value) - case that: Array[Int] => - unbox(classOf[Int]); that - case that: Array[Double] => - unbox(classOf[Double]); that - case that: Array[Float] => - unbox(classOf[Float]); that - case that: Array[Long] => - unbox(classOf[Long]); that - case that: Array[Char] => - unbox(classOf[Char]); that - case that: Array[Short] => - unbox(classOf[Short]); that - case that: Array[Byte] => - unbox(classOf[Byte]); that - case that: Array[Boolean] => - unbox(classOf[Boolean]); that - case _ => - other - } - else - other match { - case that: BoxedAnyArray[_] => - if (that.unboxed ne null) that.unboxed - else if (ScalaRunTime.isValueClass(this.elemClass)) that.unbox(this.elemClass) - else that.boxed - case that: BoxedArray[_] => - adapt(that.value) - case _ => - other - } - - override def copyFrom(src: AnyRef, from: Int, to: Int, len: Int) { - val src1 = adapt(src) - Array.copy(src1, from, if (unboxed ne null) unboxed else boxed, to, len) - } - - override def copyTo(from: Int, dest: AnyRef, to: Int, len: Int) { - var dest1 = adapt(dest) - Array.copy(if (unboxed ne null) unboxed else boxed, from, dest1, to, len) - } - - final override def filter(p: A => Boolean): BoxedArray[A] = { - val (len, include) = countAndMemo(p) - val result = new BoxedAnyArray[A](len) - var i, j = 0 - while (j < len) { - if (include(i)) { result(j) = this(i); j += 1 } - i += 1 - } - result - } -} diff --git a/src/library/scalax/runtime/BoxedArray.scala b/src/library/scalax/runtime/BoxedArray.scala deleted file mode 100755 index 47bb3a0d64..0000000000 --- a/src/library/scalax/runtime/BoxedArray.scala +++ /dev/null @@ -1,138 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: BoxedArray.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -import Predef._ -import collection.mutable.{Vector, ArrayBuffer} -import collection.generic._ - -/** - * <p>A class representing <code>Array[T]</code></p> - * - * @author Martin Odersky, Stephane Micheloud - * @version 1.0 - */ -abstract class BoxedArray[A] extends Vector[A] with MutableVectorTemplate[BoxedArray, A] with Boxed { - - /** The length of the array */ - def length: Int - - /** The element at given index */ - def apply(index: Int): A - - /** Update element at given index */ - def update(index: Int, elem: A): Unit - - /** Creates new builder for this collection ==> move to subclasses - * - * */ - def newBuilder[B] = new ArrayBuffer[B].mapResult[BoxedArray] { // !!! Adriaan: can't drop [BoxedArray] here - _.toArray.asInstanceOf[BoxedArray[B]] - } - - /** Convert to Java array. - * @param elemTag Either one of the tags ".N" where N is the name of a primitive type - * (@see ScalaRunTime), or a full class name. - */ - def unbox(elemClass: Class[_]): AnyRef - - /** The underlying array value - */ - def value: AnyRef - - def copyFrom(src: AnyRef, from: Int, to: Int, len: Int): Unit = - Array.copy(src, from, value, to, len) - - def copyTo(from: Int, dest: AnyRef, to: Int, len: Int): Unit = { - Array.copy(value, from, dest, to, len) - } - - override def equals(other: Any) = - (value == other) || - other.isInstanceOf[BoxedArray[_]] && (value == other.asInstanceOf[BoxedArray[_]].value) - - override def hashCode(): Int = value.hashCode() - - /** Fills the given array <code>xs</code> with the elements of - * this sequence starting at position <code>start</code>. - * - * @param xs the array to fill. - * @param start starting index. - * @pre the array must be large enough to hold all elements. - */ - override def copyToArray[B](xs: Array[B], start: Int, len: Int): Unit = - copyTo(0, xs, start, len) - - final def deepToString() = deepMkString(stringPrefix + "(", ", ", ")") - - final def deepMkString(start: String, sep: String, end: String): String = { - def _deepToString(x: Any) = x match { - case a: AnyRef if ScalaRunTime.isArray(a) => - ScalaRunTime.boxArray(a).deepMkString(start, sep, end) - case _ => - ScalaRunTime.stringOf(x) - } - val buf = new StringBuilder() - buf.append(start) - val elems = elements - if (elems.hasNext) buf.append(_deepToString(elems.next)) - while (elems.hasNext) { - buf.append(sep); buf.append(_deepToString(elems.next)) - } - buf.append(end) - buf.toString - } - - final def deepMkString(sep: String): String = this.deepMkString("", sep, "") - - final def deepEquals(that: Any): Boolean = { - def _deepEquals(x1: Any, x2: Any) = (x1, x2) match { - case (a1: BoxedArray[_], a2: BoxedArray[_]) => - _sameElements(a1, a2) - case (a1: AnyRef, a2: AnyRef) - if ScalaRunTime.isArray(a1) && ScalaRunTime.isArray(a2) => - _sameElements(ScalaRunTime.boxArray(a1), ScalaRunTime.boxArray(a2)) - case _ => - x1.equals(x2) - } - def _sameElements(a1: BoxedArray[_], a2: BoxedArray[_]): Boolean = { - val it1 = a1.elements - val it2 = a2.elements - var res = true - while (res && it1.hasNext && it2.hasNext) - res = _deepEquals(it1.next, it2.next) - !it1.hasNext && !it2.hasNext && res - } - that match { - case a: BoxedArray[_] => - _sameElements(this, a) - case a: AnyRef if ScalaRunTime.isArray(a) => - _sameElements(this, ScalaRunTime.boxArray(a)) - case _ => - false - } - } - - override final def stringPrefix: String = "Array" - - protected def countAndMemo(p: A => Boolean): (Int, Array[Boolean]) = { - val len = length - val memo = new Array[Boolean](len) - var count = 0 - var i = 0 - while (i < len) { - if (p(this(i))) { memo(i) = true; count += 1 } - i += 1 - } - (count, memo) - } -} diff --git a/src/library/scalax/runtime/BoxedBooleanArray.scala b/src/library/scalax/runtime/BoxedBooleanArray.scala deleted file mode 100755 index 1dc136a50f..0000000000 --- a/src/library/scalax/runtime/BoxedBooleanArray.scala +++ /dev/null @@ -1,25 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -@serializable -final class BoxedBooleanArray(val value: Array[Boolean]) extends BoxedArray[Boolean] { - - def length: Int = value.length - - def apply(index: Int): Boolean = value(index) - - def update(index: Int, elem: Boolean) { - value(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = value -} diff --git a/src/library/scalax/runtime/BoxedByteArray.scala b/src/library/scalax/runtime/BoxedByteArray.scala deleted file mode 100755 index f42dbdda38..0000000000 --- a/src/library/scalax/runtime/BoxedByteArray.scala +++ /dev/null @@ -1,25 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -@serializable -final class BoxedByteArray(val value: Array[Byte]) extends BoxedArray[Byte] { - - def length: Int = value.length - - def apply(index: Int): Byte = value(index) - - def update(index: Int, elem: Byte) { - value(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = value -} diff --git a/src/library/scalax/runtime/BoxedCharArray.scala b/src/library/scalax/runtime/BoxedCharArray.scala deleted file mode 100755 index c6f19d26e0..0000000000 --- a/src/library/scalax/runtime/BoxedCharArray.scala +++ /dev/null @@ -1,25 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -@serializable -final class BoxedCharArray(val value: Array[Char]) extends BoxedArray[Char] { - - def length: Int = value.length - - def apply(index: Int): Char = value(index) - - def update(index: Int, elem: Char) { - value(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = value -} diff --git a/src/library/scalax/runtime/BoxedDoubleArray.scala b/src/library/scalax/runtime/BoxedDoubleArray.scala deleted file mode 100755 index 16fc3e1056..0000000000 --- a/src/library/scalax/runtime/BoxedDoubleArray.scala +++ /dev/null @@ -1,25 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -@serializable -final class BoxedDoubleArray(val value: Array[Double]) extends BoxedArray[Double] { - - def length: Int = value.length - - def apply(index: Int): Double = value(index) - - def update(index: Int, elem: Double) { - value(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = value -} diff --git a/src/library/scalax/runtime/BoxedFloatArray.scala b/src/library/scalax/runtime/BoxedFloatArray.scala deleted file mode 100755 index d10f16f6f6..0000000000 --- a/src/library/scalax/runtime/BoxedFloatArray.scala +++ /dev/null @@ -1,25 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -@serializable -final class BoxedFloatArray(val value: Array[Float]) extends BoxedArray[Float] { - - def length: Int = value.length - - def apply(index: Int): Float = value(index) - - def update(index: Int, elem: Float) { - value(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = value -} diff --git a/src/library/scalax/runtime/BoxedIntArray.scala b/src/library/scalax/runtime/BoxedIntArray.scala deleted file mode 100755 index 78a033190a..0000000000 --- a/src/library/scalax/runtime/BoxedIntArray.scala +++ /dev/null @@ -1,25 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -@serializable -final class BoxedIntArray(val value: Array[Int]) extends BoxedArray[Int] { - - def length: Int = value.length - - def apply(index: Int): Int = value(index) - - def update(index: Int, elem: Int) { - value(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = value -} diff --git a/src/library/scalax/runtime/BoxedLongArray.scala b/src/library/scalax/runtime/BoxedLongArray.scala deleted file mode 100755 index 86816d6638..0000000000 --- a/src/library/scalax/runtime/BoxedLongArray.scala +++ /dev/null @@ -1,25 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -@serializable -final class BoxedLongArray(val value: Array[Long]) extends BoxedArray[Long] { - - def length: Int = value.length - - def apply(index: Int): Long = value(index) - - def update(index: Int, elem: Long) { - value(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = value -} diff --git a/src/library/scalax/runtime/BoxedShortArray.scala b/src/library/scalax/runtime/BoxedShortArray.scala deleted file mode 100755 index 6d5c82e7ba..0000000000 --- a/src/library/scalax/runtime/BoxedShortArray.scala +++ /dev/null @@ -1,25 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -@serializable -final class BoxedShortArray(val value: Array[Short]) extends BoxedArray[Short] { - - def length: Int = value.length - - def apply(index: Int): Short = value(index) - - def update(index: Int, elem: Short) { - value(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = value -} diff --git a/src/library/scalax/runtime/BoxedString.scala b/src/library/scalax/runtime/BoxedString.scala deleted file mode 100644 index ef5a8b43c7..0000000000 --- a/src/library/scalax/runtime/BoxedString.scala +++ /dev/null @@ -1,195 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: RichString.scala 15602 2008-07-24 08:20:38Z washburn $ - - -package scalax.runtime - -import scala.util.matching.Regex -import scalax.collection._ -import scalax.collection.mutable.StringBuilder -import scalax.collection.generic -import scalax.collection.generic._ - -object BoxedString { - // just statics for rich string. - private final val LF: Char = 0x0A - private final val FF: Char = 0x0C - private final val CR: Char = 0x0D - private final val SU: Char = 0x1A -} - -import BoxedString._ - -class BoxedString(val self: String) extends StringVector[Char] with Proxy with PartialFunction[Int, Char] with Ordered[String] { - - /** Return element at index `n` - * @throws IndexOutofBoundsException if the index is not valid - */ - def apply(n: Int): Char = self charAt n - - def length = self.length - - override def unbox = self - override def mkString = self - override def toString = self - - /** return n times the current string - */ - def * (n: Int): String = { - val buf = new StringBuilder - for (i <- 0 until n) buf append self - buf.toString - } - - override def compare(other: String) = self compareTo other - - private def isLineBreak(c: Char) = c == LF || c == FF - - /** <p> - * Strip trailing line end character from this string if it has one. - * A line end character is one of - * </p> - * <ul style="list-style-type: none;"> - * <li>LF - line feed (0x0A hex)</li> - * <li>FF - form feed (0x0C hex)</li> - * </ul> - * <p> - * If a line feed character LF is preceded by a carriage return CR - * (0x0D hex), the CR character is also stripped (Windows convention). - * </p> - */ - def stripLineEnd: String = { - val len = self.length - if (len == 0) self - else { - val last = apply(len - 1) - if (isLineBreak(last)) - self.substring(0, if (last == LF && len >= 2 && apply(len - 2) == CR) len - 2 else len - 1) - else - self - } - } - - /** <p> - * Return all lines in this string in an iterator, including trailing - * line end characters. - * </p> - * <p> - * The number of strings returned is one greater than the number of line - * end characters in this string. For an empty string, a single empty - * line is returned. A line end character is one of - * </p> - * <ul style="list-style-type: none;"> - * <li>LF - line feed (0x0A hex)</li> - * <li>FF - form feed (0x0C hex)</li> - * </ul> - */ - def linesWithSeparators = new Iterator[String] { - val len = self.length - var index = 0 - def hasNext: Boolean = index < len - def next(): String = { - if (index >= len) throw new NoSuchElementException("next on empty iterator") - val start = index - while (index < len && !isLineBreak(apply(index))) index += 1 - index += 1 - self.substring(start, index min len) - } - } - - /** Return all lines in this string in an iterator, excluding trailing line - * end characters, i.e. apply <code>.stripLineEnd</code> to all lines - * returned by <code>linesWithSeparators</code>. - */ - def lines: Iterator[String] = - linesWithSeparators map (line => new BoxedString(line).stripLineEnd) - - /** Returns this string with first character converted to upper case */ - def capitalize: String = - if (self == null) null - else if (self.length == 0) "" - else { - val chars = self.toCharArray - chars(0) = chars(0).toUpperCase - new String(chars) - } - - /** <p> - * For every line in this string: - * </p> - * <blockquote> - * Strip a leading prefix consisting of blanks or control characters - * followed by <code>marginChar</code> from the line. - * </blockquote> - */ - def stripMargin(marginChar: Char): String = { - val buf = new StringBuilder - for (line <- linesWithSeparators) { - val len = line.length - var index = 0 - while (index < len && line.charAt(index) <= ' ') index += 1 - buf append - (if (index < len && line.charAt(index) == marginChar) line.substring(index + 1) else line) - } - buf.toString - } - - /** <p> - * For every line in this string: - * </p> - * <blockquote> - * Strip a leading prefix consisting of blanks or control characters - * followed by <code>|</code> from the line. - * </blockquote> - */ - def stripMargin: String = stripMargin('|') - - private def escape(ch: Char): String = "\\Q" + ch + "\\E" - - @throws(classOf[java.util.regex.PatternSyntaxException]) - def split(separator: Char): Array[String] = self.split(escape(separator)) - - @throws(classOf[java.util.regex.PatternSyntaxException]) - def split(separators: Array[Char]): Array[String] = { - val re = separators.foldLeft("[")(_+escape(_)) + "]" - self.split(re) - } - - /** You can follow a string with `.r', turning - * it into a Regex. E.g. - * - * """A\w*""".r is the regular expression for identifiers starting with `A'. - */ - def r: Regex = new Regex(self) - - def toBoolean: Boolean = parseBoolean(self) - def toByte: Byte = java.lang.Byte.parseByte(self) - def toShort: Short = java.lang.Short.parseShort(self) - def toInt: Int = java.lang.Integer.parseInt(self) - def toLong: Long = java.lang.Long.parseLong(self) - def toFloat: Float = java.lang.Float.parseFloat(self) - def toDouble: Double = java.lang.Double.parseDouble(self) - - private def parseBoolean(s: String): Boolean = - if (s != null) s.toLowerCase match { - case "true" => true - case "false" => false - case _ => throw new NumberFormatException("For input string: \""+s+"\"") - } - else - throw new NumberFormatException("For input string: \"null\"") - - def toArray: Array[Char] = { - val result = new Array[Char](length) - self.getChars(0, length, result, 0) - result - } -} - diff --git a/src/library/scalax/runtime/ScalaRunTime.scala b/src/library/scalax/runtime/ScalaRunTime.scala deleted file mode 100755 index 0c8416be89..0000000000 --- a/src/library/scalax/runtime/ScalaRunTime.scala +++ /dev/null @@ -1,152 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: ScalaRunTime.scala 17000 2009-01-29 13:05:53Z odersky $ - - -package scalax.runtime - -/* The object <code>ScalaRunTime</code> provides ... - */ -object ScalaRunTime { - - def isArray(x: AnyRef): Boolean = (x != null && x.getClass.isArray) || (x != null && x.isInstanceOf[BoxedArray[_]]) - def isValueClass(clazz: Class[_]) = clazz.isPrimitive() - - def forceBoxedArray[A <: Any](xs: Seq[A]): Array[A] = { - val array = new Array[A](xs.length) - var i = 0 - for (x <- xs.elements) { array(i) = x; i += 1 } - array - } - - def checkInitialized[T <: AnyRef](x: T): T = - if (x == null) throw new UninitializedError else x - - abstract class Try[a] { - def Catch[b >: a](handler: PartialFunction[Throwable, b]): b - def Finally(handler: Unit): a - } - - def Try[a](block: => a): Try[a] = new Try[a] with Runnable { - var result: a = _ - var exception: Throwable = scala.runtime.ExceptionHandling.tryCatch(this) - - def run(): Unit = result = block - - def Catch[b >: a](handler: PartialFunction[Throwable, b]): b = - if (exception eq null) - result.asInstanceOf[b] - // !!! else if (exception is LocalReturn) - // !!! // ... - else if (handler isDefinedAt exception) - handler(exception) - else - throw exception - - def Finally(handler: Unit): a = - if (exception eq null) - result.asInstanceOf[a] - else - throw exception - } - - def caseFields(x: Product): List[Any] = { - val arity = x.productArity - def fields(from: Int): List[Any] = - if (from == arity) List() - else x.productElement(from) :: fields(from + 1) - fields(0) - } - - def _toString(x: Product): String = - caseFields(x).mkString(x.productPrefix + "(", ",", ")") - - def _hashCode(x: Product): Int = { - var code = x.getClass().hashCode() - val arr = x.productArity - var i = 0 - while (i < arr) { - val elem = x.productElement(i) - code = code * 41 + (if (elem == null) 0 else elem.hashCode()) - i += 1 - } - code - } - - def _equals(x: Product, y: Any): Boolean = y match { - case y1: Product if x.productArity == y1.productArity => - val arity = x.productArity - var i = 0 - while (i < arity && x.productElement(i) == y1.productElement(i)) - i += 1 - i == arity - case _ => - false - } - - def _equalsWithVarArgs(x: Product, y: Any): Boolean = y match { - case y1: Product if x.productArity == y1.productArity => - val arity = x.productArity - var i = 0 - while (i < arity - 1 && x.productElement(i) == y1.productElement(i)) - i += 1 - i == arity - 1 && { - x.productElement(i) match { - case xs: Seq[_] => - y1.productElement(i) match { - case ys: Seq[_] => xs sameElements ys - } - } - } - case _ => - false - } - - //def checkDefined[T >: Null](x: T): T = - // if (x == null) throw new UndefinedException else x - - def Seq[a](xs: a*): Seq[a] = null // interpreted specially by new backend. - - def arrayValue[A](x: BoxedArray[A], elemClass: Class[_]): AnyRef = - if (x eq null) null else x.unbox(elemClass) - - def boxArray(value: AnyRef): BoxedArray[_] = value match { - case x: Array[Byte] => new BoxedByteArray(x) -/* - case x: Array[Short] => new BoxedShortArray(x) - case x: Array[Char] => new BoxedCharArray(x) - case x: Array[Int] => new BoxedIntArray(x) - case x: Array[Long] => new BoxedLongArray(x) - case x: Array[Float] => new BoxedFloatArray(x) - case x: Array[Double] => new BoxedDoubleArray(x) - case x: Array[Boolean] => new BoxedBooleanArray(x) - case x: Array[AnyRef] => new BoxedObjectArray(x) -*/ - case x: BoxedArray[_] => x - } - - /** Given any Scala value, convert it to a String. - * - * The primary motivation for this method is to provide a means for - * correctly obtaining a String representation of a value, while - * avoiding the pitfalls of naïvely calling toString on said value. - * In particular, it addresses the fact that (a) toString cannot be - * called on null and (b) depending on the apparent type of an - * array, toString may or may not print it in a human-readable form. - * - * @param arg the value to stringify - * @return a string representation of <code>arg</code> - * - */ - def stringOf(arg : Any): String = arg match { - case null => "null" - case (arg : AnyRef) if isArray(arg) => boxArray(arg).deepToString - case arg => arg.toString - } -} diff --git a/src/library/scalax/runtime/StringVector.scala b/src/library/scalax/runtime/StringVector.scala deleted file mode 100644 index a612b7d7a5..0000000000 --- a/src/library/scalax/runtime/StringVector.scala +++ /dev/null @@ -1,54 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Buffer.scala 15799 2008-08-15 18:23:54Z odersky $ - - -package scalax.runtime - -import collection.immutable.Vector -import collection.mutable.ArrayBuffer -import collection.generic.VectorTemplate -import annotation.unchecked.uncheckedVariance - -object StringVector { - - implicit def unbox(sv: StringVector[Char]): String = sv.mkString - -} - -@cloneable -abstract class StringVector[+A] extends VectorTemplate[StringVector, A @uncheckedVariance] with Vector[A] { - - /** The length of the string */ - def length: Int - - /** The element at given index */ - def apply(idx: Int): A - - /** Creates new builder for this collection */ - def newBuilder[B] = new ArrayBuffer[B].mapResult[StringVector] { // !!! Adriaan: can't drop [StringVector] here - buf => new StringVector[B] { - def length = buf.length - def apply(n: Int) = buf.apply(n) - override def foreach(f: B => Unit) = buf.foreach(f) - } - } - - def unbox: String = { - val sb = new StringBuilder - for (x <- this) - sb append x.asInstanceOf[Char] - sb.toString - } - - override def toString = mkString - -} - - |