Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Moose: apply Role at Runtime (build vs. default) [solved]

by Brutha (Friar)
on Apr 02, 2013 at 12:42 UTC ( #1026677=perlquestion: print w/ replies, xml ) Need Help??
Brutha has asked for the wisdom of the Perl Monks concerning the following question:

Hello fellow monks,

after working through Moose Best Practices and various discussions, I decided to use build instead of default for my attributes. So far so good.

Now I have a role with lazy attributes that I apply at runtime with Moose::Util qw(apply_all_roles). This also works fine. With one exception. I get the message "You cannot have a lazy attribute (myattr) without specifying a default value for it". Calling the _build function from default works.

From Perl common sense I would say, the object is already built before the Role is applied. So you have to use default values for initialization. And so I do something like:

has 'myattr' => ( is => 'ro', isa => 'Int', lazy => 1, default => \&_build_myattr, # build => '_build_myattr', );

Did I miss something?

What are best practises in my case?

Thank you for your thoughts

Update: see comment below, it's a typo. It is a "builder" instead of "build"

And it came to pass that in time the Great God Om spake unto Brutha, the Chosen One: "Psst!"
(Terry Pratchett, Small Gods)

Comment on Moose: apply Role at Runtime (build vs. default) [solved]
Download Code
Replies are listed 'Best First'.
Re: Moose: apply Role at Runtime (build vs. default)
by tobyink (Abbot) on Apr 02, 2013 at 16:13 UTC

    Works for me!

    use v5.14; use strict; use warnings; package MyObject { use Moose; } package MyRole { use Moose::Role; has myattr => ( is => 'ro', lazy => 1, builder => '_build_myattr', ); sub _build_myattr { "value"; } } my $obj = "MyObject"->new; Moose::Util::apply_all_roles($obj, "MyRole"); say $obj->myattr;

    Also, whenever you call a builder method from a coderef, make sure you call it as a method so that subclassing works.

    # Not this... default => \&_build_myattr, # This! default => sub { shift->_build_myattr(@_) },
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

      First, thank you for your answer. Guess what, it works for me as well :(

      The reason for my late answer is, that my problem is a bit more complex. I have a base class and create on the fly a Role and then a Class from that Role and the baseclass. Later I apply that role with the default/builder problem. Putting that together in my sample code works as well with builders.

      Now I try to figure out where the difference is between my real code and the sample, as the real code still does give that error. (Not) Using MooseX::Declare does not make a difference.

      And it came to pass that in time the Great God Om spake unto Brutha, the Chosen One: "Psst!"
      (Terry Pratchett, Small Gods)

Re: Moose: apply Role at Runtime (build vs. default)
by Brutha (Friar) on Apr 08, 2013 at 12:49 UTC

    Hurray, finally I solved it.
    Stupid, as always in such cases.

    Take a look at my attribute's code:

    has 'myattr' => ( is => 'ro', isa => 'Int', lazy => 1, default => \&_build_myattr, # build => '_build_myattr', );

    Simply exchanging the comment between "default" and "build" does not work and gives the mentioned error.
    I also had to make a builder out of build. I had to debug deep into Moose until I found this typo

    Thank You for Your patience.

    And it came to pass that in time the Great God Om spake unto Brutha, the Chosen One: "Psst!"
    (Terry Pratchett, Small Gods)

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (8)
As of 2015-07-31 03:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (274 votes), past polls