/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2008, 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.Break._
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 length
with operand len
.
* returns x
where
* x < 0
iff this.length < len
* x == 0
iff this.length == len
* x > 0
iff this.length > len
.
*
* 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 length
*/
def size = length
/** Is this partial function defined for the index x
?
*/
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 p
,
* 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 C
consisting of all elements of
* this sequence in reverse order.
* @note the operation is implemented by building a new sequence
* from this(length - 1), ..., this(0)
* 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, this
and
* the argument, that
are infinite sequences
* this method may not terminate.
*
* @return true if that
is contained in
* this
, at the specified index, otherwise false
*
* @see String.startsWith
*/
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 that
is a prefix of this
,
* 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 that
not contained in this, otherwise the
* index where that
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 elem
is a member of this
* sequence.
*
* @param elem element whose membership has to be tested.
* @return true
iff there is an element of this sequence
* which is equal (w.r.t. ==
) to elem
.
*/
def contains(elem: Any): Boolean = exists (_ == elem)
/** Computes the union of this sequence and the given sequence
* that
.
*
* @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 that
* 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
* that
.
*
* @param that the sequence of elements to remove from this sequence.
* @return this sequence without the elements of the given sequence
* that
.
*/
def diff[B >: A](that: Sequence[B]): CC[A] = this remove (that contains _)
/** Computes the intersection between this sequence and the given sequence
* that
.
*
* @param that the sequence to intersect.
* @return the sequence of elements contained both in this sequence and
* in the given sequence that
.
*/
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 from
* and extending up to the length of the current sequence
*
* @param from The index of the first element of the slice
* @throws IndexOutOfBoundsException if from < 0
* @deprecated use drop
instead
*/
@deprecated def slice(from: Int): Sequence[A] = slice(from, length)
/** @deprecated Should be replaced by
*
* (s1, s2) forall { case (x, y) => f(x, y) }
*/
@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 that
a slice in this?
* @deprecated Should be repaced by indexOf(that) != -1
*/
@deprecated def containsSlice[B](that: Sequence[B]): Boolean = indexOf(that) != -1
}