Skip to content

Commit

Permalink
Streamline docs on .reduce(), and note it can be a "right fold" too.
Browse files Browse the repository at this point in the history
  Not crazy about that "Practical example", but left it.
  Also using &[op] when introducing [op] is still kinda suboptimal
  • Loading branch information
skids committed Jul 29, 2016
1 parent 830c485 commit 8170492
Showing 1 changed file with 27 additions and 16 deletions.
43 changes: 27 additions & 16 deletions doc/Type/List.pod6
Expand Up @@ -785,36 +785,45 @@ Usage:
LIST.reduce(CODE)
Generates a single "combined" value from a list of arbitrarily many of values,
by repeatedly applying a function which knows how to combine I<two> values.
More precisely, the specified C<&with> is first called for the first two
values of the list, then for the result of that calculation and the third
value, and so on - and the final result is returned. In other words,
C<(2, 4, 6, 8).reduce(*+*)> is the same as C<(((2+4)+6)+8)>.
by iteratively applying a function which knows how to combine I<two> values.
If C<@values> contains just a single element, that element is returned
immediately. If it contains no elements, an exception is thrown. For this
immediately. If it contains no elements, an exception is thrown, unless
C<&with> is an I<operator> with a known identity value. For this
reason, you may want to prefix the input list with an explicit identity
value:
say reduce { $^a ~ $^b }, '', |@strings; # like @strings.join
say reduce { $^a > $^b ?? $^a !! $^b }, 0, |@numbers; # like @numbers.max
As a special case, if C<&with> is the function object of an I<operator>, its
If C<&with> is the function object of an I<operator>, its
inherent identity value and associativity is respected - in other words,
C<(VAL1, VAL2, VAL3).reduce(&[OP])> is the same as C<VAL1 OP VAL2 OP VAL3> even
for operators which aren't left-associative, and an empty C<@values> list is
allowed now. And since reducing with an infix operator is a common thing to do,
the C<[ ]> meta-operator provides a syntactic shortcut:
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; # 81
(2**(3**4)).lsb.say; # 81
(2**3**4).lsb.say; # 81
# Subtract 4 from -1, because 2 minus 3 is -1
[2,3,4].reduce(&[-]).say; # -5
((2-3)-4).say; # -5
(2-3-4).say; # -5
Since reducing with an infix operator is a common thing to do, the C<[ ]>
meta-operator provides a syntactic shortcut:
# The following all do the same thing...
say reduce { $^a + $^b }, 0, |@numbers;
say reduce * + *, 0, |@numbers;
say reduce &[+], @numbers;
say [+] @numbers;
say reduce &[+], @numbers; # operator does not need explicit identity
say [+] @numbers; # most people write it this way
Since C<reduce> is an implicit loop, it responds to C<next>, C<last> and
C<redo> statements inside C<&with>:
Since C<reduce> is an implicit loop, it responds to C<next>, C<last> and C<redo>
statements.
say (2,3,4,5).reduce: { last if $^a > 7; $a + $^b }; # says 9
Practical example:
Expand All @@ -828,8 +837,10 @@ Practical example:
}
I<Note:> In the functional programming world, this operation is generally
called a L<left fold|
called a L<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.
=head2 routine combinations
Expand Down

0 comments on commit 8170492

Please sign in to comment.