txt: ## reduce.md
  reduce
  
  Combined from primary sources listed below.
  
  # [In List](#___top "go to top of document")[§](#(List)_routine_reduce "direct link")
  
  See primary documentation
  [in context](/type/List#routine_reduce)
  for **routine reduce**.
  
  ```raku
  multi method reduce(Any:D: &with)
  multi        reduce (&with, +list)
  ```
  
  Returns a single "combined" value from a list of arbitrarily many values, by iteratively applying a routine which knows how to combine *two* values. In addition to the subroutine and the list, an initial value can be provided to initialize the reduction, which ends up being the return value if the list is empty. Thus `reduce f, init, list` combines the elements of the list from left to right, as is shown in the following pseudocode:
  
  ｢Pseudo｣ without highlighting
  
  ```
  
  
  ```
  
  result0 = init
  result1 = f(result0, list[0])
  result2 = f(result1, list[1])
  ...
  resultn = f(resultn-1, list[n-1])
  
  
  ```
  
  
  ```
  
  `resultn` is the final result for an n-element list.
  
  ```raku
  say reduce &infix:<+>, (1, 2, 3); # OUTPUT: «6␤»
  say (1, 2, 3).reduce: &infix:<+>; # OUTPUT: «6␤»
  say reduce &max, (5, 9, 12, 1);   # OUTPUT: «12␤»
  ```
  
  If `list` contains just a single element, the operator is applied to that single element if possible; if not, it returns the element itself.
  
  ```raku
  say reduce &infix:<->, (10,);     # OUTPUT: «10␤»
  ```
  
  When the list contains no elements, an exception is thrown, unless `&with` is an *operator* with a known identity value (e.g., the identity value of `infix:<+>` is 0). For this reason, you're advised to prefix the input list with an initial value (or explicit identity value):
  
  ```raku
  my \strings = "One good string!", "And one another good string!";
  say reduce { $^a ~ $^b }, '', |strings;               # like strings.join
  
  my \numbers = 1, 2, 3, 4, 5;
  say reduce { $^a > $^b ?? $^a !! $^b }, 0, |numbers; # like numbers.max
  
  sub count-and-sum-evens( (Int \count, Int \sum), Int \x ) {
      x %% 2 ?? (count+1, sum+x) !! (count, sum)
  }
  
  say reduce &count-and-sum-evens, (0, 0), |numbers;    # OUTPUT: «(2 6)␤»
  ```
  
  In the last example, since `reduce` only supports one initial value we use a `List` with two values, which is by itself a single value. The `count-and-sum-evens` subroutine takes two positional values: a `List` of two [`Int`](/type/Int)s and an [`Int`](/type/Int), and return a `List` storing the count and sum of the even integers accumulated.
  
  If `&with` is the code object of an *operator*, its inherent identity value and associativity is respected - in other words, `(VAL1, VAL2, VAL3).reduce(&infix:<OP>)` is the same as `VAL1 OP VAL2 OP VAL3` even for operators which aren't left-associative:
  
  ```raku
  # Raise 2 to the 81st power, because 3 to the 4th power is 81
  (2,3,4).reduce(&infix:<**>).lsb.say;  # OUTPUT: «81␤»
  (2**(3**4)).lsb.say;                  # OUTPUT: «81␤»
  (2**3**4).lsb.say;                    # OUTPUT: «81␤»
  
  # Subtract 4 from -1, because 2 minus 3 is -1
  (2,3,4).reduce(&infix:<->).say;       # OUTPUT: «-5␤»
  ((2-3)-4).say;                        # OUTPUT: «-5␤»
  (2-3-4).say;                          # OUTPUT: «-5␤»
  ```
  
  Since reducing with an infix operator is a common thing to do, the [reduction metaoperator](/language/operators#Reduction_metaoperators) `[ ]` provides a syntactic shortcut. Thus, instead of passing the operator's code object to `reduce`, just pass the operator directly to `[ ]`. To use a user-defined subroutine instead, provide an additional layer of square brackets around the subroutine's code object:
  
  ```raku
  say [*] (1, 2, 3, 4);       # OUTPUT: «24␤»
  say [min] (4, 2, 1, 3);     # OUTPUT: «1␤»
  
  sub mult { $^a * $^b };
  say [[&mult]] (1, 2, 3, 4); # OUTPUT: «24␤»
  ```
  
  Semantically, all the following do the same thing:
  
  ```raku
  my \numbers = 1, 2, 3, 4, 5;
  say reduce { $^a + $^b }, 0, |numbers;
  say reduce * + *, 0, |numbers;
  say reduce &[+], numbers; # operator does not need explicit identity value
  say [+] numbers;
  ```
  
  Since `reduce` is an implicit loop that iterates over with its *reducing* subroutine, it responds to `next`, `last` and `redo` statements inside `&with`:
  
  ```raku
  sub last-after-seven { last if $^a > 7; $^a + $^b };
  say (2, 3, 4, 5).reduce: &last-after-seven; # OUTPUT: «9␤»
  ```
  
  Whether `reduce` accumulates the elements starting from the left or from the right depends on the operator. In the functional programming world, this operation is generally called a [fold](https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29#Folds_on_lists). With a right-associative operator it is a *right fold*, otherwise (and usually) it is a *left fold*. In Raku, you can specify the associativity of an operator with the [`is assoc`](/language/functions#index-entry-is_assoc) trait.
  
  ```raku
  sub infix:<foo>($a, $b) is assoc<right> { "($a, $b)" }
  say [foo] 1, 2, 3, 4; # OUTPUT: «(1, (2, (3, 4)))␤»
  
  sub infix:<bar>($a, $b) is assoc<left> { "($a, $b)" }
  say [bar] 1, 2, 3, 4; # OUTPUT: «(((1, 2), 3), 4)␤»
  ```
  
  **Practical example 1:** In this example, we generate a random-ish math formula (e.g., "(4 + ((3 \* x) + 11) / 6))") using `reduce`.
  
  ```raku
  my @ops = [Z] (<+ - * />, 1..20)».roll(4);
  
  say ('x', |@ops).reduce: -> $formula, [$op, $number] {
      Bool.pick ?? "($formula $op $number)"
                !! "($number $op $formula)"
  }
  ```
  
  **Practical example 2:** Suppose we have a polynomial represented as a list of integer coefficients, c[n-1], c[n-2], ..., c[0], where c[i] is the coefficient of xi. We can evaluate it using `map` and `reduce` as follows:
  
  ```raku
  sub evaluate(List:D \c where c.all ~~ Int, Rat:D \x --> Rat:D) {
      my \xi = (c.elems ^... 0).map: -> \i { x ** i }; # [x^(n-1), ..., x^0]
      my \axi = [+] c Z* xi;                           # [c[n-1]*x^(n-1), ..., c[*]x^0]
      [+] axi;                                         # sum of axi
  }
  
  my \c = 2, 3, 1;       # 2x² + 3x + 1
  say evaluate c, 3.0;   # OUTPUT: «28␤»
  say evaluate c, 10.0;  # OUTPUT: «231␤»
  ```
  
  # [In Any](#___top "go to top of document")[§](#(Any)_routine_reduce "direct link")
  
  See primary documentation
  [in context](/type/Any#routine_reduce)
  for **routine reduce**.
  
  ```raku
  multi method reduce(Any:U: & --> Nil)
  multi method reduce(Any:D: &with)
  multi        reduce (&with, +list)
  ```
  
  This routine combines the elements in a list-y object, and produces a single result, by applying a binary subroutine. It applies its argument (or first argument for the sub form) as an operator to all the elements in the object (or second argument for the sub form), producing a single result. The subroutine must be either an [infix operator](/language/operators#index-entry-infix_operator) or take two positional arguments. When using an infix operator, we must provide the code object of its subroutine version, i.e., the operator category, followed by a colon, then a list quote construct with the symbol(s) that make up the operator (e.g., `infix:<+>`). See [Operators](/language/operators).
  
  ```raku
  say (1..4).reduce(&infix:<+>);   # OUTPUT: «10␤»
  say reduce &infix:<+>, 1..4;     # OUTPUT: «10␤»
  say reduce &min, 1..4;           # OUTPUT: «1␤»
  
  sub hyphenate(Str \a, Str \b) { a ~ '-' ~ b }
  say reduce &hyphenate, 'a'..'c'; # OUTPUT: «a-b-c␤»
  ```
  
  Applied to a class, the routine will always return [`Nil`](/type/Nil).
  
  ```raku
  say Range.reduce(&infix:<+>);    # OUTPUT: «Nil␤»
  say Str.reduce(&infix:<~>);      # OUTPUT: «Nil␤»
  ```
  
  See [List.reduce](/type/List#routine_reduce) for a more thorough discussion.
  
  # [In Supply](#___top "go to top of document")[§](#(Supply)_method_reduce "direct link")
  
  See primary documentation
  [in context](/type/Supply#method_reduce)
  for **method reduce**.
  
  ```raku
  method reduce(Supply:D: &with --> Supply:D)
  ```
  
  Creates a "reducing" supply, which will emit a single value with the same semantics as [List.reduce](/type/List#routine_reduce).
  
  ```raku
  my $supply = Supply.from-list(1..5).reduce({$^a + $^b});
  $supply.tap(-> $v { say "$v" }); # OUTPUT: «15␤»
  ```
  