Maybe this is just a day at the beach for some of you fancy type programmers.
One invert function:
- works on sequential collections, parallel collections, Iterators,
Arrays, Strings, etc.
- preserves Stream laziness (something not presently accomplished by
e.g. zipped)
- is installed with an implicit conversion which takes only three
type parameters (for Tuple3) and no implicit parameters
(this being important in Predef for implicit search performance reasons)
The one change I had to make to the collections (and it should be
immaterial unless you need it) to achieve this lovely sameness of
implementation is to add this interface:
trait Container[+A, +CC[X] <: GenTraversableOnce[X]] extends Any
with GenTraversableOnce[A]
Because there is so far as I can tell no common parent to Iterator and
Traversable which preserves the shape of the container.
I just called it "Container". It doesn't have to be that, but please
for god's sake don't suggest I should call it
"GenTraversableOnceLike". Let's have something sanely named at the
very top of the hierarchy to which we can program when we're not
overly concerned with the distinctions among the many different ways
of bunching stuff.
Feedback solicited. (Silence is endorsement.) The total patch is quite
small, see for yourself.
https://github.com/paulp/scala/compare/master...topic%2Finvert
scala> (Iterator(1), Iterator("a"), Iterator(Array(1))).invert
res0: Iterator[(Int, String, Array[Int])] = non-empty iterator
scala> (Array(1), Array("a"), Array(Array(1))).invert
res1: Array[(Int, String, Array[Int])] = Array((1,a,Array(1)))
scala> (List(1), List("a"), List(Array(1))).invert
res2: List[(Int, String, Array[Int])] = List((1,a,Array(1)))
scala> (Seq(1), List("a"), Vector(Array(1))).invert
res3: Seq[(Int, String, Array[Int])] = List((1,a,Array(1)))
scala> (Vector(1), List("a"), Seq(Array(1))).invert
res4: scala.collection.immutable.Vector[(Int, String, Array[Int])] =
Vector((1,a,Array(1)))
scala> (Stream from 1, Stream from 2, Stream from 3).invert
res5: scala.collection.immutable.Stream[(Int, Int, Int)] = Stream((1,2,3), ?)
scala> ("abc", "def", "ghi").invert
res6: scala.collection.immutable.IndexedSeq[(Char, Char, Char)] =
Vector((a,d,g), (b,e,h), (c,f,i))
scala> (1 to 10 par, 1 to 10 par, 1 to 10 par).invert
warning: there were 3 feature warnings; re-run with -feature for details
res7: scala.collection.parallel.immutable.ParSeq[(Int, Int, Int)] =
ParVector((1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5), (6,6,6),
(7,7,7), (8,8,8), (9,9,9), (10,10,10))