Lazy sequence — это специальная обёртка над коллекцией, которая позволяет отложить выполнение вычислений (filter, map и т.д.) до момента непосредственного доступа к элементам. Это значит, что операции над lazy sequence будут вычислены только тогда, когда к их результату обратятся (например, при вызове .forEach, .first, преобразовании в массив и др.).
Когда использовать:
Пример:
let numbers = Array(1...1_000_000) let lazyNumbers = numbers.lazy.map { $0 * 2 }.filter { $0 % 3 == 0 } let first = lazyNumbers.first // Только сейчас вычислится цепочка операций для первого подходящего элемента!
Подводные камни:
Чем отличается вызов
.map { ... }от.lazy.map { ... }на массиве?
Ответ:
.map { ... } применяет closure к каждому элементу и возвращает новый массив сразу, то есть все элементы будут обработаны и сохранены в памяти..lazy.map { ... } возвращает не массив, а lazy-sequence (обёртку), которая не выполняет обработку элементов сразу, а только при доступе к ним.Пример:
let a = Array(1...10) let eagers = a.map { $0 * 2 } // Массив с 10 элементами let laziers = a.lazy.map { $0 * 2 } // LazySequence, не содержащий сразу результатов
История
В большом проекте разработчик применил цепочку из нескольких вызовов map, filter, reduce к огромному массиву данных без .lazy. Это привело к временному аллоцированию больших массивов на каждый промежуточный шаг, увеличило потребление памяти почти в два раза и спровоцировало краши на некоторых устройствах с низким объёмом ОЗУ.
История
В блоке кода была использована lazy sequence с побочным эффектом во внутреннем замыкании (например, send event или print внутри map/filter). Разработчик ожидал, что эта операция выполнится немедленно, однако событие не произошло вообще — потому что к элементам lazy sequence ни разу не обратились, и код с событием не был вызван вовсе. В результате логи и метрики оказались некорректными.
История
В случае сбора статистики по данным из большой базы использовали lazy sequence в сочетании с несколькими проходами (например, дважды искали first, а потом считали count). Каждый проход по lazy sequence инициировал полный пересчёт операций — что привело к двукратному замедлению и ненужной нагрузке на систему. После замены на обычный массив проблема исчезла.