Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re: Introspection of Moose/Mouse attributes fails to find native trait with `does`

by stvn (Monsignor)
on Aug 24, 2011 at 19:01 UTC ( #922171=note: print w/ replies, xml ) Need Help??


in reply to Introspection of Moose/Mouse attributes fails to find native trait with `does`

Just setting the "isa" to "Bool" is not doing what you think it is doing. You want to actually add the "Bool" Trait like so

package MyCow; use Moose; # or Mouse has "guernsey" => traits => [ 'Bool' ], is => "rw", isa => "Bool", ;
At which point $attr->does("Moose::Meta::Attribute::Native::Trait::Bool") will return true.

-stvn


Comment on Re: Introspection of Moose/Mouse attributes fails to find native trait with `does`
Select or Download Code
Re^2: Introspection of Moose/Mouse attributes fails to find native trait with `does`
by chromatic (Archbishop) on Aug 24, 2011 at 19:06 UTC
    Just setting the "isa" to "Bool" is not doing what you think it is doing.

    Out of curiosity, why not? The OP's code surprises me too.

      At a glance, I'd say:

      Perl's DOES defaults to ISA since Perl can't distinguish between base classes and roles/traits.

      Moose can distinguish between base classes and roles/traits, so it doesn't need to fallback to Perl's inaccurate default.

        Perl's DOES defaults to ISA since Perl can't distinguish between base classes and roles/traits.

        Perl 5's DOES defaults to isa() because I wrote it that way, because I understand Liskov's substitution principle.

        If DOES means "Can I treat this invocant as if it were an object of that type?" (and it does), then clearly an object which is an instance of that type or a subclass of that type should return a true value for that question.

      First the question is are Roles and Types are Symmetric. In Moose they are not, effectively Roles are a subset of Types in Moose. This means that just because an attribute has a Type, and a value that satisfies that Type is stored, that does not automatically mean that an attribute’s value does a Role equivalent to that Type. There may not be a Role that is equivalent to that type.

      Second, and it took me a second to notice this, but he’s checking the Attribute MetaObject’s does(). The Type is a property of the value stored in the attribute, not necessarily a property of the attribute itself. So even if the first were resolved such that a Type automatically implied a Role on the value, this check wouldn’t be the proper one for it.

      Third, if the poster is in fact looking to test a property of the MetaObject, and if we all agree that the best way to test/implement this is via a Role on the MetaObject, I’m not sure calling that trait after the Type name is the most intelligent design choice. It would lead to a collision with the way Moose’s implicit type auto-vivification happens.

        Second, and it took me a second to notice this, but heís checking the Attribute MetaObjectís does().

        Yeah, and that's a user interface question. I could argue that interpretation both ways, depending on how I felt about metacircularity.

        There may not be a Role that is equivalent to that type.

        I've said this before, but I'll write it again to clarify for everyone else:

        Any declaration of a type which does not imply the existence of a role is broken, in my opinion. A system is allomorphic only if every named class or type implies a role.

        With that said, a system doesn't have to be allomorphic to be useful, but a fully allomorphic system has the fewest possible edge cases and the greatest possible flexibility, and that's pretty much exactly what we're after with roles.

        (I don't have a formalism to specify the relationship of anonymous classes and anonymous roles because I haven't figured out a good way to specify the identity of an anonymous type. There's an easy and obvious solution but I haven't proven to my satisfaction that it's watertight.)

      Basically (and perigrin already said this sorta), the OP is introspecting a meta-object, not any kind of prototypical value that would be stored by the attribute. So really, there should be no reason that $attr->does('Bool') using the traditional meaning of does.

      Next, the whole traits => ['Bool'] thing needs to be understood. By adding the 'Bool' trait to the attribute you are really just asking Moose to (optionally) provide delegate-able methods (specific in this case to Bool values). So in this particular case you could do the following:

      has 'guernsey' => ( traitls => [ 'Bool' ], is => 'rw', isa => 'Bool', handles => { be_a_guersey => 'set', dont_be_a_guernsey => 'unset', } );
      Which would then allow the OP to do:
      my $cow = MyCow->new; $cow->be_a_guernsey();
      and get exactly the same behavior as his old code. Basically the Native Traits are only related to types in that they provide specific sets of behaviors for some native Perl types. And they are only related to roles in that they are implemented as roles that are applied to the attribute meta-object.

      So, while I can see that these things can be a little misleading initially. Once you learn what all the pieces are made of, and roughly how they fit together, it should make sense going forward because it is really pretty consistent.

      -stvn

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://922171]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2014-07-13 07:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (248 votes), past polls