Name

Yet Another Perl 6 Operator: Reduce Operators - Part I

Version

Maintainer: Adriano Ferreira <ferreira@cpan.org>
Date: 21 Dec 2007
Last Modified: 22 Dec 2007
Number: 14
Version: 3
Status: Draft

Body

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 .

See Also

The negate meta-operator

Chained comparisons

$Revision: 113 $