Мне действительно нравятся функциональные концепции программирования, но я был укушен в двух отдельных случаях сейчас по той же самой игре, при сопоставлении с коллекцией, которая является Set
(т.е. автоматически удаляет дубликаты). Проблема заключается в том, что после преобразования элементов такого набора выходной контейнер также является множеством, и поэтому удаляет любые дубликаты преобразованного вывода.
Очень короткий сеанс REPL, чтобы проиллюстрировать проблему:
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
Я бы, конечно, ожидал, что общий возраст будет 18 + 18 + 19 = 55, а потому, что ученики были сохранены в Set
, так же как и их возраст после сопоставления, поэтому один из 18
исчез раньше возрасты были суммированы.
В реальном коде это часто более коварно и сложнее обнаружить, особенно если вы пишете код утилиты, который просто берет Traversable
и/или использует вывод методов, объявленных для возврата Traversable
(реализация который представляет собой набор). Мне кажется, что эти ситуации почти невозможно обнаружить надежно, пока/если они не проявятся как ошибка.
Итак, есть ли какие-либо рекомендации, которые уменьшат мою подверженность этой проблеме? Нехорошо думать о map
-переходе над общим Traversable как концептуально трансформируя каждый элемент на место, а не добавляя преобразованные элементы в свою очередь к некоторой новой коллекции? Должен ли я называть .toStream
на все перед сопоставлением, если я хочу сохранить эту ментальную модель?
Приветствуются любые советы/рекомендации.
Обновление. Большинство ответов до сих пор были сосредоточены на механике включения дубликатов в сумму. Меня больше интересует практика, связанная с написанием кода в общем случае - вы просверлили себя, чтобы всегда вызывать toList
в каждой коллекции до вызова map
? Вы старательно проверяете конкретные классы всех коллекций в своем приложении, прежде чем вызывать методы на них? Etc.
Фиксирование чего-то, что уже было идентифицировано как проблема, тривиально - трудная часть предотвращает проникновение этих ошибок в первую очередь.