Я знаю, что это Traversable
, Вы должны только иметь a foreach
метод. Iterable
требует iterator
метод.
И наборы SID Scala 2.8 и "Борьба Bitrot с Типами" бумага в основном тихи на предмет почему Traversable
был добавлен. SID только говорит "David McIver... предложенного Проходимый как обобщение Повторяемых".
Я неопределенно заключил из обсуждений 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
}
Я подозреваю, что одна из причин заключается в том, что намного проще написать конкретную реализацию для коллекции с абстрактным методом foreach
, чем для одного с абстрактным методом итератора
. Например, на C # вы можете написать реализацию метода GetEnumerator
для IEnumerable
, как если бы это был метод 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)
}
Я спросил об этом Дэвида МакИвера в IRC. Он сказал, что больше не помнит все причины, но они включали:
«итераторы часто раздражают ... реализовать«
итераторы »иногда небезопасны (из-за установки / разрыва в начале и конце loop) "
Ожидаемый выигрыш в эффективности от реализации некоторых вещей с помощью foreach, а не с помощью итераторов (выигрыш еще не обязательно продемонстрирован текущим компилятором HotSpot)
только по поводу вашего последнего вопроса:
def isEmpty: Boolean = {
for (x <- this)
return false
true
}
Это примерно переводится компилятором на:
def isEmpty: Boolean = {
this.foreach(x => return false)
true
}
Таким образом, вы просто не можете выйти из foreach, isEmpty всегда будет возвращать true.
Вот почему был сконструирован «хакерский» Breakable, который выходит из foreach, генерируя исключение Control-Exception, перехватывая его в breakable
и возвращая его.