Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

JonathanWorthington (6049)

JonathanWorthington
  (email not shown publicly)
http://www.jnthn.net/
Saturday January 17, 2009
01:09 PM

Parametric Roles

[ #38308 ]

I meant to blog about what I was working on a bit more this week, but have ended up with my head in the code all week instead. The end result of this "codeathon" is that I'm now much further forward on my Hague grant. While some of the smaller tasks scheduled for December remain to be done, I have taken parametric roles from non-existent to doing everything I aimed to get them to do during January and some of the February aspects of them now work too. I've also done some work on the dispatcher refactor, got us distinguishing different routine types and have also used the end result to get submethod dispatch working as it should too. So, some details on the parametric roles.

In Perl 6, roles can take parameters. Roles exist to enable greater re-use of code than we could get through having plain old classes, and by allowing them to be parameterized we open the door to even more re-use. Taking a simple example, imagine we wanted to factor out a "greet" method into a role, which takes somebody's name and greets them. We want to parameterize it on the greeting.

role Greet[Str $greeting] {
    method greet() { say "$greeting!"; }
}
class EnglishMan does Greet["Hello"] { }
class Slovak does Greet["Ahoj"] { }
class Lolcat does Greet["OH HAI"] { }
EnglishMan.new.greet(); # Hello
Slovak.new.greet(); # Ahoj
Lolcat.new.greet(); # OH HAI

Similarly, we could do a role for requests.

role Request[Str $statement] {
    method request($object) { say "$statement $object?"; }
}
class EnglishMan does Request["Please can I have a"] { }
class Slovak does Request["Prosim si"] { }
class Lolcat does Request["I CAN HAZ"] { }
EnglishMan.new.request("yorkshire pudding");
Slovak.new.request("borovicka");
Lolcat.new.request("CHEEZEBURGER");

Sadly, the Slovak output sucks here. Borovicka is the nominative form of the word, and we need to decline it into the accusative case. But some languages don't care about that, and we don't want to have to make them all supply a transform. Thankfully, you can write many roles with the same short name, and a different signature, and multi-dispatch will pick the right one for you. So we write something to produce the accusative case in Slovak and pass it in. Here's the new code.

role Request[Str $statement] {
    method request($object) { say "$statement $object?"; }
}
role Request[Str $statement, &transform] {
    method request($object) {
        say "$statement " ~ transform($object) ~ "?";
    }
}
module Language::Slovak {
    sub accusative($nom) {
        # ...and before some smartass points it out, I know
        # I'm missing some of the masculine animate declension...
        return $nom.subst(/a$/, 'u');
    }
}
class EnglishMan does Request["Please can I have a"] { }
class Slovak does Request["Prosim si", &Language::Slovak::accusative] { }
class Lolcat does Request["I CAN HAZ"] { }
EnglishMan.new.request("yorkshire pudding");
Slovak.new.request("borovicka");
Lolcat.new.request("CHEEZEBURGER");

Which means we can now properly order our borovicka in Slovakia, which is awesome. Until you do it in a loop and find the Headache['very bad'] role got mixed into yourself overnight, anyway...

I'll post more on the other bits I'm working on, or have worked on, soon. But parametric roles are the biggy. I'm not at all finished with them yet, but all of the code examples I gave here today now work. :-)

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Excellent, nice to see progress on this feature, it is one I have been very much looking forward too.

    Did you give Sartak's MooseX::Roles::Parameterized [cpan.org] a look? It of course does not have the nice syntax, but it is very nice.

    - Stevan

    • I ported these examples [perl.org] to MooseX-Role-Parameterized. :)

      • Nice! I didn't notice this module before now, but it appears to capture the concept, just - as you say - without the more compact syntax Perl 6 offers.

        It's certainly nice that these abstractions are available for Perl 5 programmers, not least because Perl 5 is useful for doing Real Work now and Perl 6 ain't quite there yet, but also because anyone using them who might look at Perl 6 in the future will have one less thing to learn. :-)

        Thanks!

        Jonathan