/* __ *\ ** ________ ___ / / ___ 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, ::} /** Collection classes mixing in this class provide a method * elements which returns an iterator over all the * elements contained in the collection. * * @note If a collection has a known size, it should also sub-type SizedIterable. * * @author Matthias Zenger * @autor Martin Odersky * @owner Martin Odersky * @version 2.8 */ trait Iterable[+A] extends covariant.IterableTemplate[Iterable, A] { 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 Iterable. * * @author Matthias Zenger * @author Martin Odersky * @version 2.8 */ object Iterable extends covariant.IterableFactory[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()") var acc = seq.elements.next for (x <- seq) if (cmp.lt(x, acc)) acc = x acc } def max: A = { require(!seq.isEmpty, "max()") 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 covariant.IterableTemplate[C, B], A](self: C[C[A]]) { def flatten: C[A] = { val b: Builder[C, A] = self.newBuilder[A] for (xs <- self) b ++= xs b.result } def transpose: C[C[A]] = { val bs: Array[Builder[C, A]] = self.head.map(_ => self.newBuilder[A]).toArray for (xs <- self) { var i = 0 for (x <- xs) { bs(i) += x i += 1 } } type CC[B] = C[C[B]] 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 covariant.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[+UC[+B] <: Sequence[B], +A] = covariant.IterableView[UC, A] /** @deprecated use View instead */ @deprecated type Projection[+A] = View[C, A] forSome { type C[B] <: Iterable[B] } /** 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()") 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()") var max = xs.next while (xs.hasNext) { val x = xs.next if (max < x) max = x } max } }