[Perl5-syntax] Adding Moose type checking to Method::Signatures

Buddy Burden barefootcoder at gmail.com
Wed Feb 23 09:08:40 GMT 2011


Guys,

(Schwern advised me to post this over here.  If anyone thinks there's
a better venue, though, just let me know and I'm happy to move the
discussion.)

So, I'm looking to get add some type checking into Method::Signatures
(MS).  Basically, I need to replace MooseX::Method::Signatures (MXMS),
for several reasons:

*) performance--see Michael's bug #64643 filed against MXMS
*) bugs--see bugs #61070 and #63594 filed against MXMS
*) confusing error messages

I wish I was smart enough to be able to contribute a patch to MXMS
that would fix all these things, but, alas, I am not. :)  But what I
_have_ been able to do is to use MS instead, and just do the type
checking separately.  First I did this with MooseX::Params::Validate
(MXPV), which gives me the better performance, no bug with 5.12, and a
much nicer error message.  Then I scrapped MXPV altogether (since it
was checking a lot of things that MS was checking for me already), and
rolled my own using Moose::Util::TypeConstraints (MUTC) directly,
which gave me even _better_ performance, still no bug with 5.12, and I
can make my own damn error message. :)

So now I want to take it to the next step and have all this rolled
into one, instead of having type checking separately, which is a bit
clumsy.  To do what I want, I basically have two problems:

*) I need to figure out a way to use MS with MooseX::Declare (MXD).
*) I need to figure out a way to extend MS.

Now, as to the first problem, I suppose as a last resort I could do
this by telling MS to use a different keyword than "method", but I
really don't want to do that if I can help it.  In a perfect world,
I'd be using basically Perl6 syntax for classes and methods, and have
as little work to do as possible when we decide to upgrade to P6 (one
day).  I'd really consider it suboptimal if I have to declare my
methods with "mymethod" or somesuch silliness, but ANAICT MXD doesn't
use Devel::Declare::MethodInstaller::Simple the way that MS does, so
I'm not sure how to work around that.  Perhaps extending MXD ... ?

The second problem seems much easier.  After studying the MS code, I
think I can just wrap MS::inject_from_signature() and tack on another
line for each parameter with a type that looks something roughly like:

    My::Class::get_type($type) &&
My::Class::get_type($type)->check($value) || croak("Super cool error
message here");

where get_type uses MUTC to find or create the proper type constraint.
 May need a bit of tweaking here and there, but that should be roughly
it.

Now, two issues that I wanted some help with.  First, I was
considering using a syntax for the types in the signatures something
like this:

    method doit ( :$foo is Foo, :$bar is Bar )

instead of the more traditional

    method doit ( Foo :$foo, Bar :$bar )

I was thinking of doing it this way because that would allow me to
sneak by without having to change any of the parsing that MS is
already doing--it already not only reads the "is whatever" syntax, but
also reads multiples, so theoretically something like ":$foo is Foo is
ro" would work as well.  I'm not sure this syntax would be legal in
P6, but I _think_ it would be, and it seems like a reasonable
compromise.  Does this seem reasonable to everyone else as well?

If so, MS does _nearly_ all the work for me.  The parsing is all done
for me, and the type would just end up being stored in MS's internal
structs as a trait.  Then I could access that and build some extra
lines of code to do the type checking.

My second issue is that, as I mentioned, I would need to wrap
inject_from_signature.  But it looks to me like I can't override it
and just call SUPER because it's not actually a method (just a sub).
And it's not a Moose class, so I can't use "around".  So the only
thing I've been able to think of is something like:

    *Method::Signatures::orig_ifs = \&Method::Signatures::inject_from_signature;
    *Method::Signatures::inject_from_signature = \&_inject_from_signature;

    sub _inject_from_signature
    {
        my $code = Method::Signatures::orig_ifs(@_);
        # add more stuff to $code
        return $code;
    }

Again, that's just rough.  But that seems sorta ... well, hacky. :D
Is that approach kosher, or am I missing something obvious?

If anyone wants to hear any more details about my situation, just let
me know, but I figured I wouldn't drown anyone in details unless they
asked for it. :)  Any thoughts that anyone has on how I should (or
shouldn't) proceed would be much appreciated.  TIA.


            -- Buddy



More information about the Perl5-syntax mailing list