J'aime vraiment les concepts de la programmation fonctionnelle, mais j'ai été mordu à deux reprises par le même gotcha, lors de la cartographie à travers une collection qui se trouve être une Set
(c'est à dire supprime automatiquement les doublons). Le problème est que après avoir transformé les éléments de cet ensemble, le conteneur de sortie est aussi un ensemble, et donc supprime tous les doublons de la changée de sortie.
Une très brève de RÉPLICATION de session pour illustrer le problème:
scala> case class Person(name: String, age: Int)
defined class Person
scala> val students = Set(Person("Alice", 18), Person("Bob", 18), Person("Charles", 19))
students: scala.collection.immutable.Set[Person] = Set(Person(Alice,18), Person(Bob,18), Person(Charles,19))
scala> val totalAge = (students map (_.age)).sum
totalAge: Int = 37
Je serais bien sûr, s'attendre à la somme de l'âge à 18 + 18 + 19 = 55, mais parce que les étudiants ont été stockés dans un Set
, les âges après la cartographie, ainsi, l'un de la 18
s a disparu avant que les âges ont été additionnés.
Dans le code réel, c'est souvent plus insidieux et plus difficile à repérer, surtout si vous écrivez du code d'utilitaire qui prend tout simplement un Traversable
et/ou de l'utilisation de la sortie de méthodes qui sont déclarées-retour d'un Traversable
(la mise en œuvre de ce qui se trouve être un Jeu). Il me semble que ces situations sont presque impossible à repérer de manière fiable, jusqu'à ce que elles se manifestent comme un bug.
Donc, existe-il des pratiques exemplaires qui permettront de réduire mon exposition à ce problème? Suis-je tort de penser map
-ping dessus d'une Traversable que, conceptuellement, la transformation de chaque élément en place, par opposition à l'ajout de la transformée éléments en une nouvelle collection? Dois-je appeler en .toStream
sur tout avant de cartographie, si je veux garder ce modèle mental?
Des conseils/recommandations seraient grandement appréciés.
Mise à jour: la Plupart des réponses ont porté sur la mécanique de l', y compris les doublons dans la somme. Je suis plus intéressé par les pratiques en cause lors de l'écriture de code dans le cas général - avez-vous percé-vous toujours appel toList
sur toutes les collections avant d'appeler map
? Avez-vous méticuleusement vérifier les classes concrètes de toutes les collections dans votre application avant d'appeler des méthodes sur eux? Etc.
La fixation de quelque chose qui a déjà été identifié comme un problème est trivial - la partie la plus difficile est de prévenir ces erreurs rampant dans la première place.