Scala неявное или явное преобразование с итератора в iterable

Предоставляет ли Scala встроенный класс, утилиту, синтаксис или другой механизм для преобразования (путем обертывания) Iterator с помощью Iterable?

Например, у меня есть Iterator [Foo], и мне нужен Iterable [Foo], поэтому в настоящее время я:

 val foo1: Iterator[Foo] = ....
 val foo2: Iterable[Foo] = new Iterable[Foo] {
   def elements = foo1
 }

Это кажется уродливым и ненужным. Какой лучший способ?

Ответ 1

Iterator имеет метод toIterable в Scala 2.8.0, но не в 2.7.7 или ранее. Это не подразумевается, но вы можете определить свое собственное неявное преобразование, если оно вам понадобится.

Ответ 2

Вы должны быть очень осторожны, когда-либо неявно преобразовывая Iterator в Iterable (я обычно использую Iterator.toList - явно). Причиной этого является то, что, передав результат в метод (или функцию), который ожидает Iterable, вы потеряете контроль над ним в той степени, в которой ваша программа может быть нарушена. Вот один пример:

def printTwice(itr : Iterable[String]) : Unit = {
    itr.foreach(println(_))
    itr.foreach(println(_))
}

Если Iterator каким-то образом неявно конвертируется в Iterable, что напечатает следующее:

printTwice(Iterator.single("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