Re: Notes about MooseX::Role::Parameterized
Karen, thanks for the advice! Let me see if I can get unconfused: I don't want to pass a type parameter to the role - I want it to construct it! This is why I have a builder. I'd really like it to construct $type on its own, based on package name. What's the best way to do that? Or should I just quit being cute and do something like with Role => {child => __PACKAGE__}; Come to think of it, it really isn't so bad. :-) Still, I am curious to understand if parameterized roles will support a real builder and how to achieve it. On Apr 22, 2010, at 4:49 PM, Karen Etheridge wrote: You are getting an error because the role is attempting to create an attribute that doesn't exist, because you don't pass a type parameter to the role. You should mark that parameter as required, or check that it exists first, e.g. one of: parameter 'type' =>( isa => 'Str', required => 1, builder => '_type', ); or: if (my $type = $p->type) { has $type =>(is => 'rw'); } You could also use a default instead of a builder: parameter 'type' =>( isa => 'Str', default => 'human', ); The error message certainly isn't clear, and it suggests that the parameter object does not exist at all in the parameterized role when you do not pass a parameter (which does not parallel normal Moose behaviour -- an attribute metaobject always exists on the object, even if one constructs an object with no values). On Thu, Apr 22, 2010 at 04:31:20PM -0700, Kate Yoak wrote: Here is the most straightforward approach that fails with the error above (the error occurs while trying to use Me): package Role; use MooseX::Role::Parameterized; sub _type{ 'human'; } parameter 'type' =>( isa => 'Str', required => 0, builder => '_type', ); role{ my $p = shift; my $type = $p->type; has $type =>(is => 'rw'); }; 1; package Me; use Moose; with 'Role' => { }; 1; -- New and stirring things are belittled because if they are not belittled, the humiliating question arises, "Why then are you not taking part in them?" - H.G.Wells . ... . Karen Etheridge, ka...@etheridge.ca GCS C+++$ USL+++$ P+++$ w--- M++ http://etheridge.ca/ PS++ PE-- b++ DI e++ h (-)
Re: Notes about MooseX::Role::Parameterized
You are getting an error because the role is attempting to create an attribute that doesn't exist, because you don't pass a type parameter to the role. You should mark that parameter as required, or check that it exists first, e.g. one of: parameter 'type' =>( isa => 'Str', required => 1, builder => '_type', ); or: if (my $type = $p->type) { has $type =>(is => 'rw'); } You could also use a default instead of a builder: parameter 'type' =>( isa => 'Str', default => 'human', ); The error message certainly isn't clear, and it suggests that the parameter object does not exist at all in the parameterized role when you do not pass a parameter (which does not parallel normal Moose behaviour -- an attribute metaobject always exists on the object, even if one constructs an object with no values). On Thu, Apr 22, 2010 at 04:31:20PM -0700, Kate Yoak wrote: > Here is the most straightforward approach that fails with the error > above (the error occurs while trying to use Me): > > package Role; > use MooseX::Role::Parameterized; > > sub _type{ 'human'; } > > parameter 'type' =>( >isa => 'Str', >required => 0, >builder => '_type', > ); > role{ >my $p = shift; >my $type = $p->type; >has $type =>(is => 'rw'); > }; > > 1; > > package Me; > use Moose; > with 'Role' => { }; > 1; > -- New and stirring things are belittled because if they are not belittled, the humiliating question arises, "Why then are you not taking part in them?" - H.G.Wells . ... . Karen Etheridge, ka...@etheridge.ca GCS C+++$ USL+++$ P+++$ w--- M++ http://etheridge.ca/ PS++ PE-- b++ DI e++ h(-)
Re: Notes about MooseX::Role::Parameterized
parameter foo => (is => 'rw', builder => '_foo'); with _foo() defined above this statement, below it, inside the role block (pretty sure it fails before getting inside the role). No good. It says: Error: Class::MOP::Class::__ANON__::SERIAL::1 does not support builder method ... You should have the builder method defined outside the role {} block, i.e. at the same level as the parameter declaration itself. Can you give an example where you would need to define the builder inside the role block? This sounds rather strange to me. HI Karen, thanks for the help. No reason for the builder to be inside the role{} block. I was just trying everything to make it work. Here is the most straightforward approach that fails with the error above (the error occurs while trying to use Me): package Role; use MooseX::Role::Parameterized; sub _type{ 'human'; } parameter 'type' =>( isa => 'Str', required => 0, builder => '_type', ); role{ my $p = shift; my $type = $p->type; has $type =>(is => 'rw'); }; 1; package Me; use Moose; with 'Role' => { }; 1;
Re: Notes about MooseX::Role::Parameterized
On Thu, Apr 22, 2010 at 03:25:41PM -0700, Kate Yoak wrote: > Another issue: > > Can parameter use builder and have it defined within the same module? > > I've tried > > parameter foo => (is => 'rw', builder => '_foo'); > > with _foo() defined above this statement, below it, inside the role > block (pretty sure it fails before getting inside the role). No > good. It says: Error: Class::MOP::Class::__ANON__::SERIAL::1 does > not support builder method ... > > What should I do? You should have the builder method defined outside the role {} block, i.e. at the same level as the parameter declaration itself. Can you give an example where you would need to define the builder inside the role block? This sounds rather strange to me. -- "I felt a kind of forlorn sense of being lost in a world of incredibly stupid and malicious dwarfs." - Aleister Crowley . ... . Karen Etheridge, ka...@etheridge.ca GCS C+++$ USL+++$ P+++$ w--- M++ http://etheridge.ca/ PS++ PE-- b++ DI e++ h(-)
Re: Notes about MooseX::Role::Parameterized
On Thu, Apr 22, 2010 at 02:54:07PM -0700, Kate Yoak wrote: > Just a couple of notes that would be of use if they were in the > documentation: > > 1. The bad news: Because of the weirdness of role{} block, the child, > nor the role cannot be declared within the same file with the script. > (Like you might do while trying to test sample functionality!) Are you sure? e.g. have you tried including each namespace in its own block? Otherwise, each package is polluting each other's namespaces. (Alternatively, you could use namespace::autoclean.) { package MyRole; use MooseX::Role::Parameterized; role {}; 1; } { package MyClass; use Moose; with MyRole => {}; 1; } package main; my $obj = MyClass->new(); print "obj is: " . $obj->dump(1); -- "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brian W. Kernighan . ... . Karen Etheridge, ka...@etheridge.ca GCS C+++$ USL+++$ P+++$ w--- M++ http://etheridge.ca/ PS++ PE-- b++ DI e++ h(-)
Re: Notes about MooseX::Role::Parameterized
Another issue: Can parameter use builder and have it defined within the same module? I've tried parameter foo => (is => 'rw', builder => '_foo'); with _foo() defined above this statement, below it, inside the role block (pretty sure it fails before getting inside the role). No good. It says: Error: Class::MOP::Class::__ANON__::SERIAL::1 does not support builder method ... What should I do? On Apr 22, 2010, at 2:54 PM, Kate Yoak wrote: Just a couple of notes that would be of use if they were in the documentation: 1. The bad news: Because of the weirdness of role{} block, the child, nor the role cannot be declared within the same file with the script. (Like you might do while trying to test sample functionality!) 2. The good news: You can declare regular attr and methods outside of the role block (only parameterized declarations need to be there) e.g. the following orphaned role is legal: package Role; use MooseX::Role::Parameterized; has name => (is => 'rw'); role{}; 1; The usefulness is in the realization that not the entirety of the role must belong in the role {} block - but just the parameterized part. That said, I am very excited about the functionality! Thanks!