Day 6: Going Into Hyperspace

Day 6: Going Into Hyperspace

pmichaud introduced Perl 6’s hyper operators yesterday. I’d like to explore these powerful meta operators further.

First, for simplicity I’m going to code a helper function, lsay, to easily get nice-looking output of lists. The sub is created using our so you can use it on the REPL.

our sub lsay(@a) { @a.perl.say }

Then we can start looking at hyperoperator examples. For this post I’m going to use >> and << instead of » and «, mostly because they are easier on my eyes. (I’m afraid I may need to get glasses.) » and « are generally considered the true form of the operator, but the longer ASCII version will work as well.

First, the most basic: adding two lists of the same length:

> lsay (1, 2, 3, 4) <<+>> (3, 1, 3, 1)
[4, 3, 6, 5]
> lsay (1, 2, 3, 4) >>+<< (3, 1, 3, 1)
[4, 3, 6, 5]

If the lengths of the arrays are the same, there’s no difference between the two forms. But if the length is different:

> lsay (1, 2, 3, 4) <<+>> (3, 1)
[4, 3, 4, 5]
> lsay (1, 2, 3, 4) >>+<< (3, 1)
Sorry, right side is too short and not dwimmy.

The rule is that whatever is pointed to by the pointy end of the hyperoperator can be extended if it is shorter than the other end; it is extended by repeating the last element of that list. Whatever is at the blunt end of the hyperoperator cannot be extended. All combinations are allowed, so you can specify that only the left side can be extended (<<+<<), only the right side (>>+>>), both sides can be extended (<<+>>), or neither side can be extended (>>+<<). Single scalars extend as well:

> lsay (1, 2, 3, 4) >>+>> 2
[3, 4, 5, 6]
> lsay 3 <<+<< (1, 2, 3, 4)
[4, 5, 6, 7]

So that’s the basics of using hyperoperator with an infix operator. You can also use them with prefix and postfix operators:

> lsay ~<<(1, 2, 3, 4)
["1", "2", "3", "4"]
> my @a= (1, 2, 3, 4); @a>>++; lsay @a;
[2, 3, 4, 5]

You can also:

> lsay (0, pi/4, pi/2, pi, 2*pi)>>.sin
[0, 0.707106781186547, 1, 1.22464679914735e-16, -2.44929359829471e-16]
> lsay (-1, 0, 3, 42)>>.Str
["-1", "0", "3", "42"]

That is to say >>. works to call a method on every member of the list.

However much you are tempted to write @array>>.say, don’t do it. It may work in the current version of Rakudo, but by using the hyper operator you are promising the operation is parallelizable, and the order of the operations on the list(s) is not fixed. The hope is that future versions of Perl 6 will automatically run these operations in parallel.

Other quick notes: The hyperoperators don’t just work with the built-in set of operators. They will work with any new operator you define as well. (That works now in Rakudo, mostly.) They will work with the in-place operators, e.g. @a >>/=>> 2 to divide an entire array by 2. (This does not work in current Rakudo.) They will work with multi-dimensional lists, with trees, and with hashes; see S03 Hyper operators. (As far as I know, these do not yet work in Rakudo either.)

I don’t know too many examples yet of source code using hyperoperators extensively, though LastOfTheCarelessMen’s Vector class is a good if straightforward start — it implements an N-dimensional vector class without a single explicit loop.

8 thoughts on “Day 6: Going Into Hyperspace

  1. Thanks, the first part of this entry clarifies hyperoperators for me. The second part however I did not fully understand. Can you explain further why @a>>.say is not a good idea?

  2. Because hyperoperators do not operate on the list in any set order. So if you say (1, 2, 3, 4)>>.say, it might respond 1 2 3 4 or it might respond 4 3 1 2 or 4 2 1 3. This is because Perl 6 implementations are allowed to optimize hyperoperators by reordering them and/or running them in parallel.

  3. BTW, I screwed up the >>++ example; just as you cannot say 3++, you cannot say (1, 2, 3, 4)>>++. However, you can do:

    my @a = (1, 2, 3, 4);

    (I will try to edit the post to clean it up once the slashdotting is over.)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s