Enriching Scala collections using the method

How to add foreachWithIndex method to Scala collection?

This is what I could come up with so far:

 implicit def iforeach[A, CC <: TraversableLike[A, CC]](coll: CC) = new { def foreachWithIndex[B](f: (A, Int) => B): Unit = { var i = 0 for (c <- coll) { f(c, i) i += 1 } } } 

This does not work:

 Vector(9, 11, 34).foreachWithIndex { (el, i) => println(el, i) } 

It raises the following error:

 error: value foreachWithIndex is not a member of scala.collection.immutable.Vector[Int] Vector(9, 11, 34).foreachWithIndex { (el, i) => 

However, the code works when I explicitly apply the conversion method:

 iforeach[Int, Vector[Int]](Vector(9, 11, 34)).foreachWithIndex { (el, i) => println(el, i) } 

Output:

 (9,0) (11,1) (34,2) 

How to make it work without explicitly applying the conversion method? Thanks.

+4
source share
3 answers

You need to expand Iterable:

 class RichIter[A, C](coll: C)(implicit i2ri: C => Iterable[A]) { def foreachWithIndex[B](f: (A, Int) => B): Unit = { var i = 0 for (c <- coll) { f(c, i) i += 1 } } } implicit def iter2RichIter[A, C[A]](ca: C[A])( implicit i2ri: C[A] => Iterable[A] ): RichIter[A, C[A]] = new RichIter[A, C[A]](ca)(i2ri) Vector(9, 11, 34) foreachWithIndex { (el, i) => println(el, i) } 

output:

 (9,0) (11,1) (34,2) 

See this post from Rex Kerr for more details.

+8
source

The short answer is that you need to parameterize CC if you do, or the type of inferencer cannot understand what A . Another short answer is the way I describe this question in the answer.

To expand a bit more, you really don't need a CC <: TraversableLike reason CC <: TraversableLike - just grab Traversable and start with iforeach[A](coll: Traversable[A]) ! To use a superclass / superwrite you do not need to use Fancy type scores. If you want to do something more complex when you return another collection with a saved collection type, you need to use collectors, etc., which I describe in another question.

+4
source

If you are only interested in iterating through the index, you can just skip the entire pimping part and do something like

 coll.zipWithIndex.foreach { case (elem, index) => /* ... */ } 
+2
source

All Articles