Курс по Raku / Функционално, паралелно, реактивно и уеб програмиране / Функционално програмиране / Итератори

Протоколът на итераторите

Всяка стойност, която можете да обходите в цикъл — списък, диапазон, масив, — може да ви подаде итератор чрез метода .iterator. Итераторът има един съществен метод — pull-one, — който връща следващата стойност всеки път, когато го извикате:

my $it = (10, 20, 30).iterator;
say $it.pull-one; # 10
say $it.pull-one; # 20
say $it.pull-one; # 30

Когато стойностите свършат, pull-one връща специален страж — IterationEnd, — вместо истински елемент. Заявката за още една стойност от същия $it го показва:

say $it.pull-one =:= IterationEnd; # True

Операторът =:= проверява за същия обект и точно така разпознавате стража. Тази подробност има значение вътре в цикъл, където трябва и да запазите изтеглената стойност, и да я проверите. Ако я присвоите с =, стойността попада в контейнер и сравнението разглежда контейнера, а не IterationEnd. Лекарството е да свържете с :=, така че променливата просто да бъде онова, което pull-one е върнал:

my $it = <a b c>.iterator;
loop {
    my $v := $it.pull-one;      # свързване, а не присвояване
    last if $v =:= IterationEnd;
    say $v;
}

Цикълът отпечатва a, b, c и спира. Точно това прави цикълът for за вас под капака: той извиква .iterator върху онова, което обхождате, и продължава да вика pull-one, докато не срещне IterationEnd. Рядко ви се налага да го изписвате на ръка, но щом го направите веднъж, се вижда, че Raku всъщност обхожда итератори, а не списъци.

Практика

Направете 1 тест върху съдържанието на тази тема.

Навигация в курса

Итератори   |   Тест — Протоколът на итераторите


💪 Или преминете направо към упражнението към този раздел.