In the previous post, we saw an interesting implementation for the factorial function: ``` sub fac(Int \$n) { [*] 1..\$n } ```Okay, so how does that work? Perl 6 has a number of different "meta operators" that modify the existing operators to perform more powerful functions. The square brackets about are an example of the "reduce metaoperator"; they cause an infix operator to become a list operator that acts as though the infix was placed between each pair of elements. For example, the statement ``` [+] 1, \$a, 5, \$b ```is essentially the same as writing ``` 1 + \$a + 5 + \$b ```This gives us a handy mechanism to "sum all elements in a list": ``` \$sum = [+] @a; # sum all elements of @a ```Most of the infix operators (including user-defined operators) can be placed inside of square brackets to turn them into reductions: ``` \$prod = [*] @a; # multiply all elements of @a \$mean = ([+] @a) / @a; # calculate mean of @a \$sorted = [<=] @a; # true if elements of @a are numerically sorted \$min = [min] @a, @b; # find the smallest element of @a and @b combined ```So, in the factorial subroutine above, the expression `[*] 1..\$n` returns the product of multiplying all of 1 through \$n together. Another useful metaoperator is the "hyper" operator. Placing `»` and/or `«` (or the ASCI `>>` and `<<` equivalents) next to an operator makes it "hyper", which causes it operate on elements of lists. For example, the following calculates `@c` as the pairwise addition of the elements in `@a` and `@b`: ``` @c = @a »+« @b; ```In Perl 5, we'd generally write something like ``` for (\$i = 0; \$i < @a; \$i++) { \$c[\$i] = \$a[\$i] + \$b[\$i]; } ```which is quite a bit longer. As with the square brackets above, we can use hyper on a variety of operators, including user-defined operators: ``` # increment all elements of @xyz @xyz»++ # each element of @x is the smaller of @a and @b @x = @a »min« @b; ```We can also flip the angles to enable a scalar to act like an array: ``` # multiply each element of @a by 3.5 @b = @a »*» 3.5; # multiply each element of @x by \$m and add \$b @y = @x »*» \$m »+» \$b; # invert all elements of @x @inv = 1 «/« @x; # concatenate @last, @first to produce @full @full = (@last »~» ', ') »~« @first; ```Of course, reductions and hyper operators can be combined in expressions: ``` # calculate the sum of squares of @x \$sumsq = [+] ( @x »**» 2); ```There are many other metaoperators available, including `X` (cross), `R` (reverse), `S` (sequential). In fact, the "inplace" operators such as `+=`, `*=`, `~=`, are just meta forms created by suffixing an operator with an equals sign: ``` \$a += 5; # same as \$a = \$a + 5; \$b //= 7; # same as \$b = \$b // 7; \$c min= \$d; # same as \$c = \$c min \$d; ```
XHTML 1.0