Потік проти Погляди проти Ітераторів


136

Які відмінності між потоками, переглядами (SeqView) та ітераторами в масштабі? Це моє розуміння:

  • Вони всі ліниві списки.
  • Потоки кешують значення.
  • Ітератори можна використовувати лише один раз? Ви не можете повернутися до початку та знову оцінити значення?
  • Значення перегляду не кешовані, але ви можете оцінювати їх знову і знову?

Отже, якщо я хочу заощадити купу місця, чи варто використовувати ітератори (якщо я більше не перейду список) або перегляди? Дякую.


7
Я відповідав на це раніше, але як це знайти? зітхнути ...
Даніель К. Собрал

Відповіді:


182

По-перше, всі вони не суворі . Це має особливе математичне значення, пов'язане з функціями, але, в основному, означає, що вони обчислюються на вимогу, а не заздалегідь.

Streamце справді лінивий список. Насправді, у Scala, a Streamє Listчиєю tailє a lazy val. Після обчислення значення залишається обчисленим і повторно використовується. Або, як ви кажете, значення кешуються.

А Iteratorможе бути використаний лише один раз, тому що це вказівний перехід на колекцію, а не колекція сама по собі. Що робить його особливим у Scala, це те, що ви можете застосувати такі перетворення, як, mapі filterпросто отримати нове, Iteratorяке застосувати ці перетворення лише тоді, коли ви попросите наступного елемента.

Scala використовував для надання ітераторів, які можна було скинути, але це дуже важко підтримувати в загальному вигляді, і вони не склали версію 2.8.0.

Перегляди мають розглядатися приблизно як перегляд бази даних. Це серія перетворень, яка застосовується до колекції для створення "віртуальної" колекції. Як ви вже говорили, всі перетворення повторно застосовуються кожного разу, коли вам потрібно отримати елементи з нього.

І Iteratorвигляд, і вигляд мають відмінні характеристики пам'яті. StreamЦе приємно, але, в Scala, його головна перевага - це написання нескінченних послідовностей (зокрема, рекурсивно визначених послідовностей). Один може уникнути збереження всіх з Streamпам'яті, хоча, переконавшись , ви не тримаєте посилання на його head(наприклад, з використанням defзамість , valщоб визначити Stream).

Через штрафні санкції, спричинені переглядами, зазвичай forceслід застосовувати це після застосування перетворень або зберігати його як вигляд, якщо очікується, що коли-небудь буде витягнуто лише кілька елементів, порівняно із загальним розміром перегляду.


10
Iteratorтакож досить зручно для зондування нескінченного, і я, як правило, віддаю перевагу над потоками, де це можливо. Справжня перевага в потоках полягає в тому, що раніше доступні значення кешуються, що є серйозним благом при спробі впровадити щось на зразок послідовності вольових значень - що визначається з точки зору попередніх значень.
Кевін Райт

5
Фібоначчі є менш ніж досконалим прикладом, оскільки йому потрібні лише останні 2 попередні значення, а утримання всього потоку - марно. Функція Акермана є, мабуть, канонічним прикладом.
Юрген Стробель

4
@ JürgenStrobel Ackermann призведе до слабкої продуктивності, оскільки індексований доступ потоків є O (n). Але я погоджуюся, WRT складання.
Даніель К. Собрал

9
О, так. Це робить Stream поганим вибором для будь-якого підходу кешування.
Юрген Стробель

7
Ця відповідь надзвичайно зрозуміла, вона повинна бути частиною документації ... о, насправді вона є! Спасибі Даніелю docs.scala-lang.org/tutorials/FAQ/stream-view-iterator.html
Svend
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.