How do I add a foreachWithIndex
method on Scala collections?
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 doesn't work:
Vector(9, 11, 34).foreachWithIndex { (el, i) =>
println(el, i)
}
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 do I make it make it work without explicit application of a conversion method? Thanks.
You need to extend 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 by Rex Kerr for more information.
The short answer is that you have to parameterize CC
if you do it that way or the type inferencer can't figure out what A
is. The other short answer is do it the way I describe in the answer to this question.
To expand a little bit more, there's really no reason that you need CC <: TraversableLike
--just have it take a Traversable
and start with iforeach[A](coll: Traversable[A])
! You don't need to use fancy type bounds in order to use a superclass/supertrait. If you want to do something more complicated where you return another collection with collection type preserved, then you need to use builders and such, which I describe in the other question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With