In our last *Exploring Perl 6* post, we took a brief look at hyper operators, which allow you to apply binary or unary operators through lists as a single operation with support for automatic concurrency.

The circumfix `<< >>`

operator which transforms a normal operator into hyper-mode is actually just one of a class of operators that change the behavior of other operators. In other words, *meta operators.*

Let's take a look at a few more meta operators and how they work.

## The reduction meta operator

The circumfix `[ ]`

operator can be applied to any infix operator to turn it into a list reduction. A reduction applies the operator to the first two elements of the list, then replaces them with the result. The process continues until the list is exhausted and a single result remains. A simple example is a summation of multiple terms.

say [+] 2, 3, 4, 5; # 14

One of the most exciting features of reductions is that they have built-in support for laziness - and thus - infinite lists. By prefixing a reduction operator with `\`

, you can turn it into a lazy iterator.

my @infinity_sums = [\+] 1..*; for @infinity_sums -> $sum { say $sum; last if $sum > 100 }

In this program, `@infinity_sums`

is a lazy list; it will keep generating sums of all its values until we stop asking for them.

## The zip meta operator

The prefix `Z`

operator turns an infix operator into a zip operation. Zipping entails applying the operator to successive pairs of items from two lists.

my @foo = <a b c d>; my @bar = <9 8 7 6>; say @foo Z~ @bar; # (a9 b8 c7 d6) say @bar Z~ @foo; # (9a 8b 7c 6d)

This example applies string concatenation (`~`

) to successive elements of the arrays `@foo`

and `@bar`

.

If the two lists are of different lengths, a zip will only proceed until the shorter one is exhausted. But the special `*`

symbol can be used to cause the shorter list to repeat its last element as many times as necessary. For example, here is one way to square all of the elements of `@bar`

:

say @bar Z** 2, *

The right-hand list will generate as many twos as needed for the zip to complete.

## The cross meta operator

The prefix `X`

operator turns an infix operator into an algebraic cross operator, applying the infix operation to *every* pair of items from two lists. If used with multiplication, it produces a cross product, for example. But like other meta operators, `X`

works with everything.

say @foo X~ @bar; # (a9 a8 a7 a6 b9 b8 b7 b6 c9 c8 c7 c6 d9 d8 d7 d6)

One nice thing about the `X`

operator is that if no base operator is specified, the list-constructing comma operator is assumed. Therefore, `X`

can be used to create a list of pairs from two input lists.

my @colors = <red green blue>; my @letters = <alpha beta gamma>; say @colors X @letters; # ((red alpha) (red beta) (red gamma) (green alpha) (green beta) (green gamma) (blue alpha) (blue beta) (blue gamma))

You can also loop over the pairs and perform whatever other operation you like:

for @colors X @letters -> $pair { say "$pair.join(':')" # red:alpha, etc. }

## The reversing meta operator

The prefix `R`

operator reverses the arguments of an infix operator. This obviously won't have an effect on commutative operations, but it can be useful in combination with other operators (see below.) Here's a trivial example with division:

say 4 / 12; # 0.333333 say 4 R/ 12; # 3

## Combining operators: meta meta

Meta operators can also be combined into even more powerful constructs. For example, the reversing operator can be used to change the direction of a reduction.

my @numbers = <2 4 32 256>; say [/] @numbers; # 0.000061 say [R/] @numbers; # 1

These are only some of the most basic examples of what meta operators can do. They add a wealth of builtin options for processing data that in Perl 5 typically required cumbersome loops and additional utility libraries of list functions.

## Leave a comment