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) =&g开发者_JAVA技巧t; 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.
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
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.
(a : ListExtensions[Int]) foreach { (el, i) => println(el, i) };
Or, change the name to foreachWithIndex
精彩评论