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 from + n * step 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 (start, f(start), f(f(start)), ..., flen-1(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 } }