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

Buddy Burden barefootcoder at gmail.com
Wed Mar 2 19:54:57 GMT 2011


Michael,

> The only way the invocant will be messed up is if you deliberately subvert the
> normal method call process.
>
>    my $obj = A::Totally::Different::Class->new;
>    $obj->Some::Class::method(@args);
>
> This is something you're highly unlikely to do by accident.
>
> There's people passing the wrong arguments by mistake, and then there's people
> deliberately passing the wrong invocant.  I'm concerned with helping catch
> mistakes rather than stopping people who really want to do something crazy.

No, I definitely agree with that.  I don't want to stop anyone doing
anything crazy on purpose either; that crazy person could well be me.
:D  I just want there to be a clear way to distinguish between class
methods and object methods ... I guess that's the only thing I really
care about.  And, as you say, type-checking isn't the only way (and
possibly not the best way) to do that.

>>> Perl 6 has the "method ^foo" syntax.
>>> http://perlcabal.org/syn/S12.html#Class_methods
>>
>> Hunh.  I'm not fond of that synxtax _personally_, but if it's going to
>> be official P6 syntax, I suppose we could parse it.  Seems trivial
>> enough to do so.
>
> I'm not fond of it either.  And it's tied up with the metaclass object, so
> it's not clear how useful it is in Perl 5.

Yeah, let's just table that for now. :)

> Sorry, I'm using up all my brilliant thoughts on Test::Builder2 and my current
> client's $work.

Fair enough.  If something brilliant strikes me while I'm in there
hacking, I'll be sure to share. ;->

>> "is" checks inheritance, whereas "does" checks role composition.  So
>> they're not quite synonyms.
>
> You sure?  That's isa and does in Moose... but the MXMS traits are unrelated
> to types and roles, no?  You are talking about this:
>
>   Traits
>           method foo (Affe $bar does trait)
>           method foo (Affe $bar is trait)
>
>       The only currently supported trait is "coerce", which will attempt to
>       coerce the value provided if it doesn't satisfy the requirements of the
>       type constraint.
>
> or something else?  From the above, I read does and is as synonyms for
> applying traits.

Hunh.  You're right ... _as MXMS implements it_, "does" is just a
synonym for "is", which makes it rather useless.  That's not what I
was talking about then. :)  I believe the way P6 uses it (and
certainly the way that *I* would want to use it) is to check roles.
After all, the whole point of the role is to have a more flexible
solution for problems that are currently solved with inheritance.
And, as chromatic so eloquently put in his blog essays on roles,
sometimes duck typing just doesn't cut it.(*)  So if I'm using a role
to guarantee that a class conforms to a given interface, don't I need
a way to check that?

    method foo ($bar does Executable)
    {
        # now I know I can do this
        $bar->exec();
    }

>>> You're right that if MS doesn't implement syntax, it should die or warn rather
>>> than silently ignore it.
>>
>> Okay, so instead of having those methods in the base class be empty,
>> just have them spit out warnings?  Yeah, I could get behind that.
>> (Errors seem like overkill, but warnings are definitely appropriate:
>> Warning! Your syntax isn't really doing anything here; sorry about
>> that.)
>
> ...I'm split.  A warning at least lets the code work... but the only way to
> silence the warning is to either remove the type check or fix your types... so
> it might as well be an error...
>
> Since Method::Signatures is lexical, I don't see how you'd write code with a
> feature if you didn't intend to use it.  I'd go with an error.  At least you
> can easily trap an error.

Actually the way I've done it thus far (I've officially started the
hacking; woohoo!) is like so:

    use Method::Signatures { warn => 0 };

and that turns the warnings off.  Or we could come up with a different
(or additional) interface if you like:

    use Method::Signatures qw<:NOWARN>;

perhaps.  I just kept things so I'd have to fiddle with import() as
little as possible.

What I really wanted was something like:

    no warnings 'reserved';              # or other appropriate category

but I couldn't get that to work, so I went with the above.  But it's
simple enough to change if you have a preference.

> Yeah.  You're a committer now so there's no point in forking and merging pull
> requests is more work for me (or you).
>
> As for branching or working on master, use your head.  Keep master working.
> New features or scary bug fixes go into a branch.  When in doubt: branch.
>
> But by cloning you're always working in your own local branch.  Nothing is
> committed until you push.  So often you can just work on master in your own
> clone, do a bunch of commits, and then push when it's ready.  And as long as
> you haven't pushed you can always turn your local commits to master into a branch.

Okay, cool.  That's what I'll do then.  Seeing as how I just changed
the way invocant parsing works (it was conflicting with a class type
on the first parameter), I'd say this work qualifies as both new
feature _and_ scary bug fix. :-D  So I'll turn my clone into a branch
and we'll go from there.

Thanks for all the guidance!


            -- Buddy


(*) http://www.modernperlbooks.com/mt/2009/05/perl-roles-versus-duck-typing.html



More information about the Perl5-syntax mailing list