Курс языка программирования Raku / Функциональное, конкурентное, реактивное и веб-программирование / Функциональное программирование / Свёртка
Процедура reduce
Когда сворачивать нужно собственной операцией, а не одним именованным
оператором, используйте процедуру reduce. Она принимает
блок от двух аргументов и применяет его вдоль списка, перенося
накопленный результат дальше:
say (1..5).reduce(* + *); # 15В блоке * + * две звезды Whatever: первая — это результат,
накопленный к этому моменту, вторая — очередной элемент. Поэтому
reduce вычисляет ((((1 + 2) + 3) + 4) + 5), то
есть 15, — то же, что и [+], но записанное
блоком.
Чтобы увидеть эти два аргумента в деле, дайте им имена и напечатайте
каждый шаг. Стрелочный блок возвращает своё последнее выражение, поэтому
$x + $y — это и то, о чём блок печатает, и то значение,
которое он возвращает в reduce:
say (1..5).reduce(
-> $x, $y {
say "$x + $y";
$x + $y;
}
);Программа печатает:
1 + 2
3 + 3
6 + 4
10 + 5
15Каждая из первых четырёх строк — это один вызов блока.
$x — накопленный к этому моменту результат, $y
— очередной элемент списка. Самый первый вызов получает два первых
значения списка, 1 и 2; каждый следующий
получает обратно итог предыдущего шага как $x —
3, затем 6, затем 10, — в паре с
очередным числом как $y. Значение блока становится
$x следующего вызова, а итоговая сумма, 15, —
это то, что reduce возвращает и что say
печатает последней строкой.
Поскольку блок может быть каким угодно, reduce более
универсален. Например, можно строить значение шаг за шагом:
say (1..4).reduce(-> $acc, $x { $acc * 10 + $x }); # 1234Каждый шаг умножает накопитель на десять и прибавляет очередную
цифру, превращая отдельные цифры 1, 2, 3, 4 в число
1234.
Как и другие принимающие блок методы, reduce хорошо
читается в форме вызова с
двоеточием, где скобки вокруг блока опускаются:
say (1..5).reduce: * + *; # 15Коротко говоря, [op] — быстрая форма для именованного
оператора, а reduce — гибкая форма для произвольного
объединяющего блока. Оба сворачивают список к одному значению.
Практика
Пройдите 1 тест по содержанию этой темы.
Навигация по курсу
← Тест — Метаоператор свёртки | Тест — Свёртка →
💪 Или перейдите сразу к упражнениям этого
раздела.