[Perl5-syntax] How to test for a role in a method signature

Buddy Burden barefootcoder at gmail.com
Mon Mar 7 07:46:29 GMT 2011


Guys,

Okay, sorry to be incommunicado for a bit there.  Let me sum up my
thoughts on the discussion so far:

*) I find it difficult to argue with the concept that you should be
able to put the role name in the same place you would put a class
name.  "Similar things should look similar" is a good argument, as is
"the constraint declaration is always to the left of the parameter
name and the right hand side is for declaring stuff about how the
parameter is initialized" (both Piers).  This is also very simple to
implement, as it happens: I take my line that looks like this:

    $types{$type} = ( any_moose('::Util::TypeConstraints') .
'::find_or_parse_type_constraint' )->($_[0])
                 || ( any_moose('::Util::TypeConstraints') .
'::class_type' )->($_[0])
                 unless $types{$type};

and I make it look like this instead:

    $types{$type} = ( any_moose('::Util::TypeConstraints') .
'::find_or_parse_type_constraint' )->($_[0])
                 || ( any_moose('::Util::TypeConstraints') .
'::class_type' )->($_[0])
                 || ( any_moose('::Util::TypeConstraints') .
'::role_type' )->($_[0])
                 unless $types{$type};

Easy peasy.

*) I also find it difficult to argue with this, from Piers:

> If you _really_ want to ensure that a parameter isa Foo and also does
> Bar then you need to rethink your architecture. Or hide the pain, bite
> the bullet and make a custom type.

I just can't imagine any situation where I need to demand that a
parameter _both_ "isa" and "does".  Just doesn't make sense to me.

*) Of course, as Rev Chip points out, you still have the issue of
possibly needing both "does" and "does", and _that_ I certainly _can_
imagine.

*) As for Rev Chip's concern that:

> But there is no way
> at compile time to know which test will apply, so your proposal is
> lower at runtime.  That's a killer.

I'm not sure I agree with this, assuming I understand exactly what
he's referring to.  As you can see from the code I quoted above, once
I find (or make) the appropriate type constraint, I cache it, so,
after the first time, it's going to be pretty quick.

*) And I can cache this regardless of whether it's a class type or a
role type, because I know there's no overlap between class names and
role names--at least I know that in P5/Moose, because they're all just
package names.  I assume the same is true in P6 ...

*) On the issue of maintaining compatibility with MXMS: I certainly
hear Pier's point that:

> And what looks like a drop in replacement requires me to change every
> method definition that uses coercion and, for bonus points, doesn't
> complain until runtime when I miss one.

I think it's a good point.  *But* I have to agree with Michael that we
have to abandon compatibility with MXMS as a goal to strive for.  Not
because "changing MS has no direct effect on MXMS or MXD users"; as
soon as I finish fiddling with MS, I'm going straight over to MXD and
come up with a way to replace MXMS with MS, so it _may_ have a direct
effect on MXD users.  And I don't think it's that fruitful to quibble
over how much code might or might not be using it--that's more of an
academic debate that can't realistically go anywhere.  The reason
_I'm_ not swayed by arguments of needing to maintain compatibility
with MXMS is that I think our goal should be to come up with the best
syntax for future generations of Perl hackers, and I don't want to see
us constrained by the past here.  Similar to how Larry wasn't afraid
to break compatibility with P5 in P6.  Not that I mean to imply that
I'm as cool as Larry, but ... hubris, right? :-D  I just can't see
maintaining compatibility for the sake of compatibility, if the use of
"does" in MXMS was a bad decision.

*) So was it a bad decision?  As Michael says:

> * Using "does" to declare a trait overloads its meaning (roles and traits)
> * the meaning of "does" is stronger and more important as declaring a
>   role rather than more grammatically correct synonym to declare a trait
> * Perl 6 uses "does" these days to exclusively refer to roles

You could come up with a decent counter-argument for that first one,
maybe, but the other two?  That's a K.O. AFAIC.  Keeping "does" around
as a synonym for "is" when "does" screams "roles" at everyone is just
a Bad Idea(tm).  And maintaining compatibility with MXMS just doesn't
cut it as a reason to keep that Bad Idea(tm) around.  Not for me, at
least.

*) So Michael's final proposal:

On Sat, Mar 5, 2011 at 6:54 PM, Michael G Schwern <schwern at pobox.com> wrote:
> So I propose both.
>
>    method foo (Some::Class $thing)             # ambiguous
>    method foo ($thing isa Some::Class)         # explicit
>
>    method foo (Some::Type $thing)              # ambiguous
>    method foo ($thing type Some::Type)         # explicit
>
>    method foo (Some::Role $thing)              # ambiguous
>    method foo ($thing does Some::Role)         # explicit

works for me.  I don't care so much about the "isa" and "type" bits,
but I certainly don't mind them.  And the ability to use "does" to
specify two roles is pretty crucial ... well, the ability to specify
two roles is pretty crucial, so AFAIC any counter-proposal has to
address that issue.

And I (at least) am perfectly willing to consider any
counter-proposal.  The only thing that Michael's proposal doesn't
address is it doesn't keep the constraining on the left vs. the
parameter usage attributes on the right.  But I'm not sure I see a way
to preserve that, so I'm happy enough with it as it is.  But, as I
say, I'm willing to listen to any potential better ideas.

Now, I'm still concerned about Piers' point that, if you were to have
MXMS code and you wanted to convert over to ours--and why wouldn't
you? it's cooler, less buggy, and it runs faster--you really wouldn't
want to have to wait and find out that you missed a "does coerce"
until runtime.  So it occurs to me: I'm building my cache of type
constraints at runtime, as they're called.  But I don't _have_ to do
that, right?  Why not build the cache at compile-time, as the types
are parsed?  That way, any unrecognized type gets reported
immediately, at compile-time.  So your "does coerce" spits out an
error such as:

    Can't locate role name "coerce" (perhaps you forgot to load it?)
at foo.pm line 123.

That would work, right?


            -- Buddy



More information about the Perl5-syntax mailing list