Funky Function Filters in Perl6

Created 2011-04-07 / Edited 2011-10-16

Tags: Perl6, Rakudo, Programming

A while back I wrote about TLT - 2006.03.03 - Funky Function Filters. Let me refresh your memory - we have a Python and a Ruby snippet and we translate it into Perl5. The code is a toy to show some fancy shmancy lambda (unnamed functions) usage. The idea is to take a list of functions, filter them, and then with the remaining ones show what happens with parameters from -10 to 10.

Python example:

for f in filter(lambda f: f(-1)>=f(1),
                [lambda x:x, lambda x:x**2, lambda x:x**3]):
    for x in range(-10, 11):
        print x, f(x)

Ruby translation:

for f in [lambda { |x| x }, lambda { |x| x**2 }, lambda { |x| x**3 }
         ].select { |f| f.call(-1) >= f.call(1) }
    for x in -10..10
        print x, f.call(x)
    end
end

My perl5 translation:

for my $f (grep { $_->(-1) >= $_->(1) }
        ((sub{shift}, sub{(shift)**2}, sub{(shift)**3})) {
  for my $x (-10..10) {
    print "$x: ",$f->($x),"\n";
  }
}

Today I thought I'd give a stab at a perl6 translation (using the 2011.01 Rakudo Star release). I started with a straightforward translation from the perl5, then switched to perl6 idioms.

Perl6 translation:

for (* ** 1, * ** 2, * ** 3).grep({ $_.(-1) >= $_.(1) }) -> $f {
  for -10 .. 10 -> $x {
    say "$x: { $f.($x) }"
  }
}

The first line is a doozy! This is similar in some ways to the perl5 translation, though the grep now shows up on the righthand-side of the list like in Ruby. The biggest difference to me is in the list of lambdas:

(* ** 1, * ** 2, * ** 3)

I mean... what does THAT mean?! Let's take the last one, "* ** 3". Translated into English:

Whatever to-the-power-of 3

Wait wait... "whatever"? The Whatever-Star is a fancy thing from perl6 that took me a while to work out, and there may still be some nuances that I'm missing. In this context it magically makes a closure... er... lambda, that takes one parameter which it puts where you see the '*'.

# Whatever-Star notation
* ** 3

# Pointy-block notation
-> $x { $x ** 3 }

# Subref notation
sub ($x) { $x ** 3 }

(Note: that last one should be SLURPY! But I don't know how to do that apparently)

Enjoy... Whatever!