Reputation: 13048
Any ideas why doesn't the following work?
implicit def listExtensions[A](xs : List[A]) = new ListExtensions(xs)
class ListExtensions[A](xs : List[A])
{
def foreach[B](f: (A, Int) => B)
{
var i = 0;
for (el <- xs)
{
f(el, i);
i += 1;
}
}
}
var a = List(1, 2, 3);
a foreach { (el, i) => println(el, i) };
When I compile this with fsc 2.8.1, I get the following error: "wrong number of parameters; expected = 1: a foreach { (el, i) => println(el, i) };". Am I doing something wrong or there simply ain't a way to add an overloaded method by the means of "pimp my library" trick?
P.S. I wonder not about implementing the iterate-with-current-index flavor of foreach (I'm aware of zipWithIndex method), but rather about how overloading and implicit conversions play together.
Upvotes: 2
Views: 790
Reputation: 29163
(a : ListExtensions[Int]) foreach { (el, i) => println(el, i) };
Or, change the name to foreachWithIndex
Upvotes: 1
Reputation: 3855
The compiler never attempts to use the implicit conversion because there's already a foreach method on List. More specifically, section 7.3 of the Scala Language Specification (http://www.scala-lang.org/docu/files/ScalaReference.pdf) states that an implicit conversion is applied in two cases, with the second case relevant to the example:
In a selection e.m with e of type T, if the selector m does not denote a member of T.
As an aside, you can accomplish a foreach with an index by using the zipWithIndex method.
scala> val a = List("Java", "Scala", "Groovy")
a: List[java.lang.String] = List(Java, Scala, Groovy)
scala> a.zipWithIndex.foreach { case (el, idx) => println(el + " at index " + idx) }
Java at index 0
Scala at index 1
Groovy at index 2
Upvotes: 10
Reputation: 49705
Implicit conversion will only kick in when you attempt to use a method that doesn't exist on the source type.
In this case, List has a foreach method, so no conversion will be considered. But you will get an error for not matching the expected signature.
Upvotes: 1