Курс языка программирования Raku / Функциональное, конкурентное, реактивное и веб-программирование / Функциональное программирование / Итераторы
Написание итератора
Итератор — это просто объект, который выполняет встроенную роль
Iterator и предоставляет метод pull-one. Этот
метод возвращает следующее значение или IterationEnd, когда
ничего не осталось. Вот итератор обратного отсчёта, выдающий число и
шагающий к нулю:
class Countdown does Iterator {
has Int $.n is rw;
method pull-one {
return IterationEnd if $!n <= 0;
return $!n--;
}
}Каждый вызов pull-one сначала проверяет, не кончился ли
счёт; если нет — возвращает текущее число и уменьшает его. Постфиксное
уменьшение $!n-- возвращает значение до вычитания,
поэтому числа выходят как 3, 2, 1. Управление им вручную
выглядит как и у любого другого итератора:
my $c = Countdown.new(n => 3);
say $c.pull-one; # 3
say $c.pull-one; # 2
say $c.pull-one; # 1
say $c.pull-one =:= IterationEnd; # TrueСам по себе итератор — не то, что цикл for может взять
напрямую: циклу нужен итерируемый объект. Заверните итератор в
Seq, и по нему станет можно проходить циклом:
for Seq.new(Countdown.new(n => 3)) -> $x {
say $x;
}Это напечатает 3, 2, 1. В
повседневном коде вы взяли бы gather / take —
форма генератора для того же
результата куда короче. Но написать роль Iterator напрямую
стоит хотя бы раз, потому что это обнажает то, на чём построены
gather, map и всякий цикл for:
объект, отвечающий на один-единственный вопрос — «каково следующее
значение?».
Навигация по курсу
← Тест — Протокол итератора | Сумма с помощью pull-one →
💪 Или перейдите сразу к упражнению
этого раздела.