Почему в коллекциях Scala 2.8 тип Traversable был добавлен выше Iterable? - PullRequest
19 голосов
/ 08 апреля 2010

Я знаю, что для Traversable вам нужен только метод foreach. Iterable требуется метод iterator.

И SID коллекций Scala 2.8, и статья «Борьба с битротом с типами» в основном ничего не говорят о том, почему был добавлен Traversable. SID говорит только: «Дэвид Макивер ... предложил Traversable как обобщение Iterable».

Я смутно понял из обсуждений IRC, что это связано с восстановлением ресурсов, когда обход коллекции завершается?

Следующее, вероятно, связано с моим вопросом. В TraversableLike.scala есть некоторые странно выглядящие определения функций, например:

def isEmpty: Boolean = {
  var result = true
  breakable {
    for (x <- this) {
      result = false
      break
    }
  }
  result
}

Полагаю, есть веская причина, которая была написана не так:

def isEmpty: Boolean = {
  for (x <- this)
    return false
  true
}

Ответы [ 3 ]

11 голосов
/ 16 апреля 2010

Я спросил об этом Дэвида Макивера в IRC. Он сказал, что больше не помнил все причины, но они включали:

  • "итераторы часто раздражают ... для реализации"

  • итераторы «иногда небезопасны (из-за установки / разрыва в начале и конце цикла)»

  • Надежда на повышение эффективности от реализации некоторых вещей с помощью foreach, а не с помощью итераторов (прирост не обязательно фактически демонстрируется текущим компилятором HotSpot)

4 голосов
/ 09 апреля 2010

Я подозреваю, что одна из причин заключается в том, что написать конкретную реализацию для коллекции с абстрактным методом foreach намного проще, чем для абстрактной iterator. Например, в C # вы можете написать реализацию GetEnumerator метода IEnumerable<T>, как если бы это был foreach метод:

IEnumerator<T> GetEnumerator() 
{
    yield return t1;
    yield return t2;
    yield return t3;
}

(Компилятор генерирует соответствующий конечный автомат для запуска итерации через IEnumerator.) В Scala вам потребуется написать собственную реализацию Iterator[T], чтобы сделать это. Для Traversable вы можете сделать эквивалент вышеописанной реализации:

def foreach[U](f: A => U): Unit = {
  f(t1); f(t2); f(t3)
}
0 голосов
/ 04 июня 2010

относительно вашего последнего вопроса:

def isEmpty: Boolean = {
  for (x <- this)
    return false
  true
}

Это примерно переводится компилятором в:

def isEmpty: Boolean = {
  this.foreach(x => return false)
  true
}

Так что вы просто не можете выйти из цикла foreach, isEmpty всегда будет возвращать true.

Вот почему был создан "хакерский" Breakable, который выходит из foreach, генерируя исключение Control, исключая его в breakable и возвращая.

...