Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

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

by Your Mother (Archbishop)
on Aug 24, 2011 at 18:26 UTC ( [id://922165]=perlquestion: print w/replies, xml ) Need Help??

Your Mother has asked for the wisdom of the Perl Monks concerning the following question:

As I read the docs, the following code should report that the attribute does, Yes!, do Bool, instead of the No... it gives.

BEGIN { package MyCow; use Moose; # or Mouse has "guernsey" => is => "rw", isa => "Bool", ; } my $cow = MyCow->new; $cow->guernsey(1); print "How now, ", $cow->guernsey ? "brown" : "purple", " cow?", $/; my $attr = $cow->meta->get_attribute("guernsey"); print "Attribute does Bool? ", $attr->does("Bool") ? "Yes!" : "No...", + $/;

Do I just misunderstand? What is the right way to do this? I tried all the various names of the trait, like Moose::Meta::Attribute::Native::Trait::Bool.

Replies are listed 'Best First'.
Re: Introspection of Moose/Mouse attributes fails to find native trait with `does`
by stvn (Monsignor) on Aug 24, 2011 at 19:01 UTC

    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
      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.

        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.

        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.

        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
Re: Introspection of Moose/Mouse attributes fails to find native trait with `does`
by thargas (Deacon) on Aug 24, 2011 at 19:02 UTC
    As I understand the docs, does() tests if it implements the named Role. I think you want isa().
      No because isa() would return Moose::Meta::Attribute.
      I agree. And there is type_constraint() method to get Moose::Meta::TypeConstraint object for the attribute:
      print "Attribute does Bool? ", $attr->type_constraint->equals("Bool") +? "Yes!" : "No...", $/;
      It works well as expected.
Re: Introspection of Moose/Mouse attributes fails to find native trait with `does`
by Khen1950fx (Canon) on Aug 24, 2011 at 21:12 UTC
    I couldn't get $attr->does('Bool') to work with isa, so I took it out. This works, but is there a better way?
    package MyCow; use Moose; has 'guernsey' => ( traits => ['Bool'], is => 'rw', isa => 'Bool', ); my $cow = MyCow->new; $cow->guernsey(1); print "How now, ", $cow->guernsey ? "brown" : "purple", " cow?", $/; my $attr = $cow->meta->get_attribute('Bool'); print "Attribute does Boolean? ", $cow->guernsey ? "Yes!" : "No...", $ +/;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://922165]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2024-03-29 09:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found