collections Scala avec Enrichir une méthode
-
26-10-2019 - |
Question
Comment puis-je ajouter une méthode de foreachWithIndex
sur les collections Scala?
est ce que je pouvais venir avec à ce jour:
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
}
}
}
Cela ne fonctionne pas:
Vector(9, 11, 34).foreachWithIndex { (el, i) =>
println(el, i)
}
génère l'erreur suivante:
error: value foreachWithIndex is not a member of scala.collection.immutable.Vector[Int]
Vector(9, 11, 34).foreachWithIndex { (el, i) =>
Cependant, le code fonctionne lorsque je demande explicitement la méthode de conversion:
iforeach[Int, Vector[Int]](Vector(9, 11, 34)).foreachWithIndex { (el, i) =>
println(el, i)
}
Sortie:
(9,0)
(11,1)
(34,2)
Comment puis-je faire le faire fonctionner sans application explicite d'une méthode de conversion? Merci.
La solution
Vous devez étendre 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)
}
sortie:
(9,0)
(11,1)
(34,2)
Voir ce post par Rex Kerr pour plus d'informations.
Autres conseils
La réponse courte est que vous devez paramétrer CC
si vous le faites de cette façon ou inferencer type ne peut pas comprendre ce qui est A
. L'autre réponse courte est faire la façon dont je décris dans la réponse à cette question.
Pour développer un peu plus, il n'y a vraiment aucune raison que vous avez besoin CC <: TraversableLike
- juste ont-il un Traversable
et commencer par iforeach[A](coll: Traversable[A])
! Vous n'avez pas besoin d'utiliser des bornes de type fantaisie afin d'utiliser une superclasse / supertrait. Si vous voulez faire quelque chose de plus compliqué où vous retournez une autre collection avec le type de collection conservée, alors vous devez utiliser les constructeurs et tels que je décris dans l'autre question.
Si ce que vous intéresse est seulement itérer avec un index, vous pourriez tout aussi bien sauter toute la partie de proxénétisme et de faire quelque chose comme
coll.zipWithIndex.foreach { case (elem, index) =>
/* ... */
}