Курс 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; кожен наступний отримує назад підсумок попереднього кроку як $x3, потім 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 тест за змістом цієї теми.

Навігація курсом

Тест — Метаоператор згортки   |   Тест — Згортка


💪 Або перейдіть одразу до вправ цього розділу.