Matt Follett

Perl 6: Exciting Method Invocation

Perl 6 provides many new and interesting approaches to method invocation.  New constructs in the language allow the developer to define how many matching methods are called, how they are called, as well as a few other things.

In Line Mutators

Perl 6 supports the idea of inline mutators.  In Perl 5 it isn’t too uncommon to see code like this:

@array = sort @array

It is common enough in the Perl community to see “assign this mutated value back into the variable it came from” that Perl 6 gives a cleaner way.  The same code in Perl 6 could be written:

@array .= sort

The line above says to take @array, sort it, and put the values back in @array all in one fluid motion.  Of course, there is one motion that developers go through that is so common most probably don’t think about it:

my SVG $svg_serializer = SVG.new;

Thankfully, .= can use used here to assign a value into $svg_serializer more cleanly:

my SVG $svg_serializer .= new;

Invoking Multiple Matched Methods

In Perl5 (and other languages) one often finds code litered with statements like this:

$foo->frobinicate() if $foo->can(‘frobinicate’);

That gets old after a while.  Perl 6 solves this, and a few other problems, with a new approach to method calls that allows the developer to request 0 or 1, 1, 1 or more, or any number of methods be called at a time.  So, for example, the Perl6 equivalent of above is:

$foo.?frobinicate;

The above code will invoke the frobinicate method on $foo if one exists.  However, if no method exists that matches that criteria then nothing will be executed and instead of dying the statement simply returns Nil.

As I mentioned there are other options here also, for example if the developer wanted to execute all of the ‘frobinicate’s that existed within the inheritance hierarchy of $foo they could do either:

$foo.*frobinicate;

$foo.+frobinicate;

As readers can probably guess ‘.*’ will invoke 0 or more methods named ‘frobinicate’ on $foo returning Nill if none exist.  That leaves ‘.+’ to invoke 1 or more matching methods, the line dies if it finds no matching methods.

Here is an example of the above:

class Dog {

   method talk { ‘bark’ }

}

class TalkingDog is Dog {

   method talk { ‘Hello’ }

}

my TalkingDog $td .= new;

$td.talk # returns ‘Hello’

$td.?talk # returns ‘Hello’

$td.*talk # returns (‘Hello’, ‘bark’)

$td.+talk # also returns (‘Hello’, ‘bark’)

$td.*calculate_pi # returns Nil

$td.+calculate_pi # dies

$td.?calculate_pi # returns Nil

$td.calculate_pi # dies

Parallel Invokation

Perl 6 has an incredibly exciting new operator called the hyperoperator.  The hyperoperator indicates that the methods being invoked can be dispatched in parallel.  This makes simple cases of parallel execution very simple to do.  To do this, simply prepend ‘>>’ between the object and the invocation operator.  For example:

@foo>>.frobinicate

This would invoke ‘frobinicate’ on all the elements in @foo in parallel.  

The hyperoperator can be combined with the previous topic of invoking all the methods that match.  This makes it very simple to invoke all of the possible methods on an object in parallel:

$foo>>.*frobinicate()

Here is a simple, but more fleshed out example to wrap things up:

class Department {

   has @.employees;

   has $.name;

   method gen_print_info { return “$.name:\n” ~”\t\t” ~ @.employees.sort.join(‘, ‘)}

}

my @company = (

   Department.new( name => ‘Accounting’, ‘employees’ => <Jeff Jane Susan>),

   Department.new( name => ‘Security’, employees => <Alice Bob>),

   Department.new( name => ‘Marketing’, employees => <Margaret Terry Lawrence>),

   Department.new( name => ‘Development’, employees => <Matt Fred Steve Joe Alith Jie>)

)

my @print_info = @company>>.gen_print_info;

The example above would execute gen_print_info on all of the Department typed objects in @company.

 

Further Reading