Categories

Posts in this category

Fri, 24 Apr 2009

What you can write in Perl 6 today


Permanent link

You've probably heard of Perl 6 before; this weird new version of Perl that Larry Wall is obsessed with, and that's being worked on since the year 2000, and for which there's still no real compiler. Right?

Well, nearly. In 2000 the decision for a complete rewrite of the language was made, hacking on Parrot (a virtual machine intended to run Perl 6 and other dynamic languages) began 2001, but hacking on Rakudo, the Perl 6 compiler on top of Parrot, began in earnest in December 2007.

These days Rakudo is, in my humble opinion, fairly usable. It's not fast, and not feature complete, but it implements many neat features, and passes more than 10,000 tests today.

I've picked a few example of what Rakudo can run today, in the hope that it will impress some Perl 5 hackers and generate more interest in Perl 6 and Rakudo.

Built-in Schwartzian Transformation

This one is not overly complicated, but very handy anyway. If you want to sort an array case insensitively, in Perl 5 you'd write

# (Perl 5)
@a = sort { uc($a) cmp uc($b) } @a;

# or if you don't want to duplicate your uc effor, you do a ST:
@a = map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { [$_, uc] } @a;

(See Schwartzian Transform for details on what this does).

Perl 6's sort built-in is smart enough to recognize a block that expects only one parameter, and automatically does the ST for you:

# (Perl 6)

@a = @a.sort: { .uc };

Built-in functions don't default to $_ anymore, but a method call without invocant does, so the .uc is equivalent to $_.uc.

If you want to golf, you can write that even shorter: @a = @a.sort: *.uc. The *.method syntax automatically writes the closure for you.

Sorting Hashes

Another useful sort technique is Hash.sort. It passes Pairs (ie single key-to-value mappings) to its comparison routine, making the to hash items unnecessary that you might know from Perl 5 hash sorting code.

Sorting a Hash by value, for example, is as easy as

# (Perl 6)
my %leaders = USA => 'Obama', Germany => 'Merkel', France => 'Sarkozy';
say %leaders.sort(*.value).perl;

# Output:
# ["Germany" => "Merkel", "USA" => "Obama", "France" => "Sarkozy"]

Iterating made easy

Iterating arrays and hashes was never hard in Perl, but in Perl 6 a few things are even simpler than before. Suppose you want to iterate an array, but obtain two items in each iteration. In Perl 5 you'd either write a C-style for loop iterating over the index in steps of two, or use List::MoreUtils::natatime (if you can spell it ;-).

But this is so much easier:

for <a b c d> -> $x, $y {
    say "$x | $y";
}
# output:
# a | b
# c | d

This also helps when you want to iterate over both index and values:

for <a b c>.kv -> $k, $v {
    say "key: $k    value: $v";
}
# output:
# key: 0    value: a
# key: 1    value: b
# key: 2    value: c

The same code also works with Hashes.

Reductions

Long known to users of functional programming languages, reductions can be very easy in Perl 6. Instead of 1 + 2 + 3 you can write [+] 1, 2, 3, where [...] is the reduction meta operator.

Some examples:


say [+] 1..5;       # sum
say [*] 1..5;       # product
say [<] @list;      # is @list strictly ordered ascendingly?
say [!=] @list;     # are no two consecutive items equal?
say [eq] @list;     # are all items string-equal?

Parametric Roles

Perl 6 comes with a fully fledged object system including roles (pieces of behavior and data that can be composed into classes and objects).

Not only that, but you can also give the roles parameters, which are bound to values at composition time.

use v6;

role Tax[Num $rate] {
    method pay-tax {
        my $tax = $.income * $rate;
        $!income -= $tax;
        say "Paying $tax Dollars tax";
    }
}

class Banker {
    has $.income = 234000;
}

my $bailout = Banker.new() but Tax[0.90];
$bailout.pay-tax();
# output: Paying 210600 Dollars tax

(To get something similar in Perl 5 you'd need Mooseand MooseMooseX::Role::Parameterized]).

Parametric roles are used internally to implement typed arrays and hashes.

my Int @a = 1, 2, 3;
@a[1] = 4;      # fine
@a[2] = 'foo';  # Error: Type mismatch in assignment.

The my Int @a declares an Array that's parameterized by the type of array items, here Int.

Conclusions

These are just a few very basic examples of cool things to do with Perl 6 today. Even more exciting are for example the regexes and grammars, about which I won't talk now because then I wouldn't finish before the end of the month ;-)

If you haven't tried Perl 6, now is a good time. Download and build it now, and if you have any questions go to #perl6 on irc.freenode.net, or ask on perl6-users@perl.org.

[/perl-6] Permanent link