Day 10 – Feed operators

Anyone who has programmed in Perl 5 for a while has probably run across or written code similar to this:

    my @new = sort { ... } map { ... } grep { ... } @original;

In this construction, the data flows from the @original array which feeds into the grep, and that, in turn, feeds into the map, and then into the sort, and then finally, the result is assigned to the @new array. Because they each take a list as their final parameter, simply by juxtposition, the data feeds leftward from one operation to the next.

Perl 6, on the other hand, makes this idea of data flowing from one operation to another explicit by introducing the feed operator. The above Perl 5 code could be written like this in Perl 6:

    my @new <== sort { ... } <== map { ... } <== grep { ... } <== @original;

Note that TMTOWTDI is alive and well in Perl 6. You could have also written much the same as in Perl 5:

    my @new = sort { ... }, map { ... }, grep { ... }, @original;

The only difference would be the addition of commas.

So, what do we gain from these feed operators? Normally, when reading code, you read from left to right. In the original Perl 5 code you would read from left to right until you realize that you’re dealing with constructions where the direction of flow is right to left, then you jump to the end and follow the processing in a right-to-left manner. In Perl 6 there is now a prominent syntactic marker that clues you in to the leftward flowing nature of the data.

Still, the right-to-left nature of this code is somewhat troublesome. It may not seem so onerous if all of the code fits on one line as above. But imagine if the blocks associated with grep, map, and sort were little longer. Finding the end of the statement could be a bit annoying.

Luckily, Perl 6 has another feed operator that allows you to write the same code in a left-to-right fashion:

    @original ==> grep { ... } ==> map { ... } ==> sort { ... }  ==> my @new;

This works exactly the same as before only the direction of flow has been changed.

Here are a couple of examples of real, working Perl 6 code using the feed operators:

    my @random-nums = (1..100).pick(*);
    my @odds-squared <== sort() <== map { $_ ** 2 } <== grep { $_ % 2 } <== @random-nums;
    say ~@odds-squared;
    my @rakudo-people = <scott patrick carl moritz jonathan jerry stephen>;
    @rakudo-people ==> grep { /at/ } ==> map { .ucfirst } ==> my @who-it's-at;
    say ~@who-it's-at;