Scala обеспечивает встроенный класс, утилиту, синтаксис или другой механизм для преобразования (путем обертывания) Итератор с Повторяемым?
Например, у меня есть Итератор [Нечто], и мне нужно Повторяемое [Нечто], поэтому в настоящее время я:
val foo1: Iterator[Foo] = ....
val foo2: Iterable[Foo] = new Iterable[Foo] {
def elements = foo1
}
Это кажется ужасным и ненужным. Что такое лучший путь?
Iterator
имеет метод toIterable
в Scala 2.8. 0, но не в 2.7.7 или более ранней версии. Это не подразумевается, но вы можете определить свое собственное неявное преобразование, если оно вам нужно.
Вы должны быть очень осторожны в отношении когда-либо неявно преобразования Итератора
в Iterable
(я обычно использую Iterator.toList
- явно).Причина этого в том, что, передавая результат в метод (или функцию), который ожидает Iterable
, вы теряете контроль над ним до такой степени, что ваша программа может быть нарушена . Вот один пример:
def printTwice(itr : Iterable[String]) : Unit = {
itr.foreach(println(_))
itr.foreach(println(_))
}
Если бы Iterator
каким-то образом неявно преобразовывался в Iterable
, что напечатало бы следующее?
printTwice(Iterator.single("Hello"))
Он (конечно) будет печатать только ] Привет один раз. Совсем недавно трейт
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