Maintainer: Adriano Ferreira <ferreira@cpan.org> Date: 21 Dec 2007 Last Modified: 22 Dec 2007 Number: 14 Version: 3
Status: Draft
And that's time to take a look at another of the Perl 6 meta-operators: the reduction operator.
By surrounding with square brackets an (associative) infix operator, a new list operator is created.
[*] 1..10 # that's 1*2*...*10 = 10! [~] <m oo s e> # 'moose' - [~] is basically Perl 5 join [,] 'a'..'e' # <a b c d e> - [,] is a list builder
The derived list operator produces an operation which reduces a list into a single item by repeatedly applying the original operator. Thus,
[+] 1, 2, 3 is (1 + 2) + 3
[~] <a b c> is ('a' ~ 'b') ~ 'c'
[**] 4, 3, 2 is 4 ** (3 ** 2)
where the last example emphasizes that the reduction operator associates the same way as the operator used.
The implementation of reduction operators brings some
interesting issues to the semantics of Perl 6 operators.
The obvious solution is to derive an operator like '[+]'
from '+' by autogenerating code such as
proto prefix:<[+]> (*@args) {
my $accum = =@args;
for =@args {
$accum += $_;
}
return $accum;
}
But that's not the only alternative. Instead, the reduce
operator [foo] can define the list operator and, at the
same time, the foo infix operator. In this case,
some expressions could be rewritten by the optimizer from their original
form to another using the list operator.
# Original # Optimized $a foo $b [foo] $a, $b $a foo $b foo $c [foo] $a, $b, $c
Another case where the implementation of reduce operations bring extra knowledge to the interpretation of the original operator is defining the proper result of applying the reduction into an empty list. The result must be the identity property of the infix operator.
[*]() # 1 [+]() # 0 [~]() # '' [min]() # +Inf [X]() # []
The power of reduction operators will also allow to write an expression such as
[<] @a
to check that the elements of list @a are ordered under '<'.
And that example takes us to the definition of reduce operators
in the single-argument case. By default, if there is one
argument, the built-in reduce operators return that one argument
(which works for '+', '*', '~'). But that's not good enough
for operators like '<' (and other relational operators)
that don't return the same type as they take. That means
[+] 42 # 42 [*] -1 # -1 # but [==] 'a' # True [<] 1 # True # and [!=] 'a' # False [!eq] '' # False
Then comparison operators return a boolean for either 1 or
0 arguments. Negated operators return Bool::False,
while all the rest return Bool::True.
To get more glimpses on how Perl 6 will achieve all of this, you might like to read section "Reduction Operators" on Synopsis 03 .
$Revision: 113 $