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.

Était-ce utile?

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) =>
  /* ... */
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top