Вы должны быть очень осторожны в отношении когда-либо неявно преобразования Iterator
в Iterable
(я обычно использую Iterator.toList
- явно) Причина этого в том, что, передавая результат в метод (или функцию), который ожидает Iterable
, вы теряете контроль над ним до такой степени, что ваша программа может быть повреждена . Вот один пример:
def printTwice(itr : Iterable[String]) : Unit = {
itr.foreach(println(_))
itr.foreach(println(_))
}
Если Iterator
каким-то образом неявно преобразуется в Iterable
, что будет напечатано следующее?
printTwice(Iterator.single("Hello"))
Он будет (конечно) печатать только Hello один раз. Совсем недавно trait
TraversableOnce
был добавлен в библиотеку коллекций, которая объединяет Iterator
и Iterable
. На мой взгляд, это возможно ошибка.
Мое личное предпочтение - использовать Iterator
явно, где это возможно, а затем использовать List
, Set
или IndexedSeq
напрямую. Я обнаружил, что редко могу написать метод, который действительно не зависит от типа, который передается. Один пример:
def foo(trades: Iterable[Trade]) {
log.info("Processing %d trades", trades.toList.length) //hmmm, converted to a List
val shorts = trades.filter(_.side.isSellShort)
log.info("Found %d sell-short", shorts.toList.length) //hmmm, converted to a List again
//etc