Курс по 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 тест върху съдържанието на тази тема.

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

Тест — Метаоператорът за свиване   |   Тест — Свиване


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