Scala: в чем разница между проходимыми и повторяемыми признаками в коллекциях Scala?
Я посмотрел на этот вопрос но все еще не понимаю разницы между Итерационными и проходимыми чертами. Может кто-нибудь объяснить ?
3 ответа:
проще говоря, итераторы сохраняют состояние, а траверсы-нет.
A
Traversable
есть один абстрактный метод:foreach
. Когда вы звонитеforeach
,коллекция будет кормить переданную функцию все элементы, которые она держит, один за другим.С другой стороны,
Iterable
имеет абстрактный методiterator
, который возвращаетIterator
. Вы можете позвонитьnext
наIterator
чтобы получить следующий элемент в Вашему выбору. Пока вы этого не сделаете, он должен держать след, где он был в коллекции, и что дальше.
думайте об этом как о разнице между дуть и сосать.
когда у вас есть вызов
Traversable
sforeach
, или его производные методы, он будет выдувать свои значения в вашу функцию по одному за раз-так что он имеет контроль над итерацией.С
Iterator
возвращеныIterable
хотя, вы высасываете значения из него, контролируя, когда перейти к следующему самостоятельно.
tl; dr
Iterables
areTraversables
что можно производить с учетом состоянияIterators
во-первых, известно, что
Iterable
является подзаголовкомTraversable
.второе,
Traversable
требует реализацииforeach
метод, который используется всем остальным.
Iterable
требует реализацииiterator
метод, который используется всем остальным.например, имплементация
find
наTraversable
используетforeach
(через Для понимания) и бросает!--14--> исключение для остановки итерации после того, как удовлетворительный элемент был найден.trait TravserableLike { def find(p: A => Boolean): Option[A] = { var result: Option[A] = None breakable { for (x <- this) if (p(x)) { result = Some(x); break } } result } }
В противоположность
Iterable
вычесть переопределяет эту реализацию и вызываетfind
наIterator
, который просто перестает повторяться, как только элемент найден:trait Iterable { override /*TraversableLike*/ def find(p: A => Boolean): Option[A] = iterator.find(p) } trait Iterator { def find(p: A => Boolean): Option[A] = { var res: Option[A] = None while (res.isEmpty && hasNext) { val e = next() if (p(e)) res = Some(e) } res } }
было бы неплохо не бросать исключения для
Traversable
итерации, но это единственный способ частично итерация при использовании толькоforeach
.С одной точки зрения,
Iterable
является более требовательной / мощной чертой, так как вы можете легко реализоватьforeach
используяiterator
, но вы не можете действительно реализоватьiterator
используяforeach
.
в целом,
Iterable
предоставляет способ приостановить, возобновить или остановить итерацию с помощью statefulIterator
. СTraversable
, это все или ничего (без исключений для управления потоком).большую часть времени это не имеет значения, и вы будете нужен более общий интерфейс. Но если вам когда-нибудь понадобится более индивидуальный контроль над итерацией, вам понадобится
Iterator
, который вы можете получить отIterable
.