Курс языка программирования Raku / Функциональное, конкурентное, реактивное и веб-программирование / Функциональное программирование / Генераторы
Ленивый gather
Блок gather ленив: он не выполняется весь
сразу. Он выдаёт значения лишь по мере того, как их вытягивают, а это
значит, что gather может описывать
бесконечную череду и всё равно оставаться полезным: вы
просто перестаёте брать значения, когда их достаточно.
Загвоздка в том, что результат надо сохранить ленивым. Складывание
его в обычный @array попыталось бы собрать сразу все
значения, а для бесконечной череды это никогда не закончится. Вместо
этого держите последовательность в скаляре (там она остаётся ленивой
Seq) и вытягивайте из неё срез:
my $naturals = gather {
my $n = 1;
loop {
take $n++;
}
}
say $naturals[^5]; # (1 2 3 4 5)Цикл loop не кончается никогда, но производится ровно
пять значений, потому что именно столько мы и запросили через
[^5]. Вытягивать с начала можно и методом
.head:
say (gather { my $n = 1; loop { take $n++ } }).head(3); # (1 2 3)Именно лень и позволяет gather безопасно моделировать
бесконечные потоки: ничего не вычисляется, пока не понадобится, и вы
берёте ровно столько, сколько хотите.
Навигация по курсу
← Тест — gather и take | Соберите кубы →
💪 Или перейдите сразу к упражнениям этого
раздела.