Perl 6 Is Fun

This post got a lot of discussion on Hacker News that you might find interesting.

I’ve been writing a fair bit of Perl 6 lately, and my main takeaway so far is that Perl 6 is fun.

Pretty much everything I love in Perl 5 is still part of Perl 6, but almost everything I hate is gone too.

$Love - $Hate = $Fun;

Here are some of the things that I’ve been having fun with in Perl 6 …

Built-In OO and Types

I really love that I can write this in native Perl 6:

use v6;
unit class Pod::To::HTML::Renderer is Pod::To::HTML::InlineListener;

has Cool $!title;
has Cool $!subtitle;
has Cool $!prelude;
has Cool $!postlude;

Of course, you can already do pretty much the same thing with Moose in Perl 5, except now I don’t have to debate Moose vs Moo vs Moops vs STOP MAKING SO DARN MANY “M” MODULES!

Roles work just as well with a simple role Foo { ... } declaration.

Multiple Dispatch

If you’ve ever written an API for parsing a text format as a stream of events in Perl 5, you’ve probably ended up with something like this:

sub start_bold { ... }
sub end_bold { ... }

sub start_heading { ... }
sub end_heading { ... }

And of course to dispatch it you write something like this:

sub dispatch {
    my $self = shift;
    my $node = shift;

    my $type = $node->type;
    my $start = 'start_' . $type;
    my $end   = 'end_' . $type;

    $self->listener->$start($node);
    ... # deal with node contents
    $self->listener->$end($node);
}

That’s not terrible, but it’s so much more elegant with multiple dispatch in Perl 6. Here’s our listener with multiple dispatch:

multi method start (Node::Bold $node) { ... }
multi method end (Node::Bold $node) { ... }

multi method start (Node::Heading $node) { ... }
multi method end (Node::Heading $node) { ... }

# And let's catch unexpected nodes
multi method start (Any:D $node) { ... }
multi method end (Any:D $node) { ... }

given/when and smartmatching

There was an attempt to put this in Perl 5 but it never worked out because this feature really needs a solid type system and ubiquitous OO to work properly.

method walk-pod (Any:D $node, Int $depth = 0) {
    self!maybe-end-all-lists( $node, $depth );

    given $node {
        when Array { # Array is a type name - this is like $node->isa('Array') in Perl 5
            self.walk-pod( $_, $depth + 1 ) for $node.values;
        }
        when Pod::Item { # same again
            ...
        }
        default {
            self!send-events-for-node( $node, $depth );
        }
    }
}

Smartmatching also dovetails nicely with Perl 6’s junctions:

given $node.name {
    when 'Image' {
        ... # do something with an image
    }
    when any  {
        ... # do something with HTML
    }
    when any @semantic-meta-blocks {
        self.handle-semantic-block( $node, :meta );
    }
}

Easy Threading

Spinning off a few threads to do work in parallel is pretty easy. Just make a Supply and call its throttle method. Tell it the maximum number of threads to use and give it a Routine to do the work.

method !run-with-progress ($items, Routine $sub, Str $msg = q{   done}) {
    my $prog = Term::ProgressBar.new( :count( $items.elems ), :p )
        if $!verbose;

    my $i = 1;
    my $supply = $items.Supply.throttle(
        $!threads,
        -> $item {
            $sub($item);
            $prog.?update($i++);
        }
    );
    $supply.wait;

    $prog.?message($msg);
}

So Many Little Things

Did you catch that $prog.?update($i) call in the method above? If $prog has the method I’m looking for, the method is called, otherwise it does nothing. If the object wasn’t created, then $prog is an Any object, which doesn’t have an update method.

And I haven’t even had a chance to use features like grammars, built-in set operations, or a native call interface that lets you define the mapping between Perl 6 and C with some trivial Perl 6 code. If you’ve ever written XS you will appreciate just how wonderful that interface is!

Also, the Perl 6 community has been great to work with, answering all my questions (dumb or not), and even improving an error message within about 10 minutes of my suggestion that it was unclear! Of course, the Perl 5 community is pretty great for the most part too, so that’s nothing all that new (although no one can patch anything in the Perl 5 core in 10 minutes ;).