Я розглянув це питання, але досі не розумію різниці між ознаками, які можна відмінити і відміняти. Може хтось пояснить?
Я розглянув це питання, але досі не розумію різниці між ознаками, які можна відмінити і відміняти. Може хтось пояснить?
Відповіді:
Простіше кажучи, ітератори зберігають стан, траверси - ні.
TraversableМає один абстрактний метод: foreach. Коли ви телефонуєте foreach, колекція передаватиме переданій функції всі елементи, які вона зберігає, один за одним.
З іншого боку, Iterableмає як абстрактний метод iterator, який повертає Iterator. Ви можете зателефонувати next, Iteratorщоб отримати наступний елемент під час вашого вибору. Поки ви цього не зробите, він повинен відслідковувати, де він був у колекції, і що далі.
Iterableпоширюється Traversable, тому я думаю, ви маєте на увазі Traversables, які не є Iterables.
Traversableінтерфейсу не вимагає збереження стану, а дотримання Iteratorінтерфейсу.
Traversables, які Iterableне зберігають жодного ітераційного стану. Це Iteratorстворене та повернене тим, Iterableщо утримує державу.
Подумайте про це як про різницю між видуванням та смоктанням.
Коли ви викликаєте Traversables foreachабо його похідні методи, він почне вводити свої значення у вашу функцію по одному - значить, він має контроль над ітерацією.
З Iteratorповерненим, Iterableоднак, ви висмоктуєте з нього значення, контролюючи, коли самостійно перейти до наступного.
tl; dr - Iterables це Traversablesте , що може призвести до стануIterators
По-перше, знайте, що Iterableце підручне зображення Traversable.
По-друге,
Traversableвимагає впровадження foreachметоду, який використовується всім іншим.
Iterableвимагає впровадження iteratorметоду, який використовується всім іншим.
Наприклад, реалізація findдля Traversableвикористання foreach(через розуміння) та викид для BreakControlвиключення ітерації після виявлення задовільного елемента.
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надається спосіб призупинити, відновити чи зупинити ітерацію за допомогою стану Iterator. З Traversable, це все або нічого (не допускає винятків для контролю потоку).
Більшу частину часу це не має значення, і вам потрібно більш загальний інтерфейс. Але якщо вам коли-небудь потрібен більш налаштований контроль над ітерацією, вам знадобиться документ Iterator, який ви можете отримати з Iterable.
Відповідь Даніеля звучить добре. Дозвольте мені побачити, чи можу я сказати це своїми словами.
Таким чином, Ітерабельний може дати вам ітератор, який дозволяє вам перетинати елементи один за одним (використовуючи next ()), а також зупинятися та їхати як завгодно. Для цього ітератору необхідно зберегти внутрішній «покажчик» на позицію елемента. Але Траверсай дає вам метод, передбачити, щоб пройти всі елементи одразу, не зупиняючись.
Щось на зразок діапазону (1, 10) повинно бути лише 2 цілих числа, як стан як прохідний. Але Діапазон (1, 10) як Ітерабельний дає вам ітератор, який повинен використовувати 3 цілі числа для стану, одне з яких - індекс.
Зважаючи на те, що Traversable також пропонує foldLeft, foldRight, його передбачати потрібно, щоб перемістити елементи у відомому та фіксованому порядку. Тому можливо реалізувати ітератор для прохідного каналу. Напр. Def iterator = toList.iterator
Traversableв Scala 2.13 (вона до сих пір зберігається в якості псевдоніма для минаєIterableдо 2.14)