routine reduce
Documentation for routine reduce assembled from the following types:
class List
From List
(List) routine reduce
Defined as:
multi sub reduce(, *)multi method reduce(List: )
Generates a single "combined" value from a list of arbitrarily many of values, by iteratively applying a function which knows how to combine two values.
If @values contains just a single element, the operator is applied to that single element if possible; if not, it returns the element itself.
say [-] <10 5 3>; #OUTPUT: 2say [-] 10; #OUTPUT: 10
If it contains no elements, an exception is thrown, unless &with is an operator with a known identity value. For this reason, you may want to prefix the input list with an explicit identity value:
my = ("One good string!", "And one another good string!");say reduce , '', |; # like @strings.joinmy = (1,2,3,4,5);say reduce , 0, |; # like @numbers.max
If &with is the function object of an operator, its inherent identity value and associativity is respected - in other words, (VAL1, VAL2, VAL3).reduce(&[OP]) is the same as VAL1 OP VAL2 OP VAL3 even for operators which aren't left-associative:
# Raise 2 to the 81st power, because 3 to the 4th power is 81[2,3,4].reduce(&[**]).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(&[-]).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 [ ] metaoperator provides a syntactic shortcut:
# The following all do the same thing...my = (1,2,3,4,5);say reduce , 0, |;say reduce * + *, 0, |;say reduce &[+], ; # operator does not need explicit identitysay [+] ; # most people write it this way
Since reduce is an implicit loop, it responds to next, last and redo statements inside &with:
say (2,3,4,5).reduce: ; # says 9
Practical example:
# Generate a random-ish math formula like "(4 + ((3 * x) + 11) / 6))"my = [Z] (<+ - * />, 1..20)».roll(4);say ('x', |).reduce: -> , [, ]
Note: In the functional programming world, this operation is generally called a fold. With a right-associative operator it is a right fold, otherwise (and usually) it is a left fold:
sub infix:<foo>(, ) is assoc<right>say [foo] 1, 2, 3, 4; # OUTPUT: «(1, (2, (3, 4)))»sub infix:<bar>(, ) is assoc<left>say [bar] 1, 2, 3, 4; # OUTPUT: «(((1, 2), 3), 4)»
class Supply
From Supply
(Supply) method reduce
method reduce(Supply: --> Supply)
Creates a "reducing" supply with the same semantics as List.reduce.
my = Supply.from-list(1..5).reduce();.tap(-> ); # OUTPUT: «15»