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

Moose and BUILD and 'ro' attributes

by Brutha (Friar)
on Dec 15, 2010 at 09:32 UTC ( [id://877225]=perlquestion: print w/replies, xml ) Need Help??

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

Hello all,

I am quite new to Moose but making progress. For a real world problem I have now the following Problem. Consider some attributes. The first contains initialization data (from a config-file), the second is build from this data, let's say a pathname. As the configuration never changes, both should be read-only.

First scenario, the configuration is raw data and passed to the constructor. The path-attribute has a lazy builder, which can access the config data. That is easy.

Second scenario, I have config data, two pathnames and want to create a third attribute - parameter string - from these. I could use BUILD to initialize all my attributes, which would become rather complex. This could be made more readable by using attribute builders.

Now my questions:
How do I set read-only variables in BUILD?
Which is called first, BUILD or the attribute_builders?

Thank You for helping

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

Replies are listed 'Best First'.
Re: Moose and BUILD and 'ro' attributes
by moritz (Cardinal) on Dec 15, 2010 at 09:58 UTC
    The first contains initialization data (from a config-file), the second is build from this data, let's say a pathname.

    If it's built from the data, why have an attribute for it? Is it a very expensive calculation?

    Reading Moose::Manual::Construction it seems that you could write a BUILDARGS sub that generates the second attribute based on the first one. Then Moose's internal mechanisms set the ro attributes, you don't have to do it.

    Finally, in my limited understanding "ro" just means that no public accessor for changing the object is created - you can still change it through $self->{yourattribute} = $new_value inside the class.

Re: Moose and BUILD and 'ro' attributes
by Khen1950fx (Canon) on Dec 15, 2010 at 10:42 UTC
Re: Moose and BUILD and 'ro' attributes
by Brutha (Friar) on Dec 15, 2010 at 10:48 UTC

    Thank You for pointing out at Moose::Manual::Construction, which is not about Moose construction, but constructing objects in Moose. I should not have ignored that :-(

    In short, the problem is I read Log4Perl initialization from a file, for two logfiles, one technical log and one specialized log changing over the time. To create the second one on-the-fly I use the patterns from the config to create a layout class and an appender, which is later used to generate the second logfile. The reason for this is that File-Appenders create the files on construction, but I do not have a filename at that time. So I gather and create all things I need at the beginning to use them when I first have a logfilename. Later I can use file_switch() on the appender but that is Log4Perl. Expensive? I really do not know. My philosophy/religion is that constant things should be initialized at the beginning, when they are used more than once.

    I think You are right, I might solve this by reordering my builders and revisting the examples.

    Thank You again 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)

      Yes, it is probably possible to solve this just by re-thinking the order of events and what actually depends on what. You can usually come up with some workable chain of events using lazy loading. I would also not be too fuzzed about the time of creation of the attribute - if you use lazy the attribute is guaranteed to be populated before you use it the first time, which should be all that matters. In some cases, setting a trigger for an attribute might also help to resolve some more complicated dependencies.
Re: Moose and BUILD and 'ro' attributes
by stvn (Monsignor) on Dec 15, 2010 at 15:44 UTC
    How do I set read-only variables in BUILD?

    Why not just make a private writer, like this

    has 'foo' => ( is => 'ro', isa => 'Something', writer => '_set_foo', lazy => 1, build => '_build_foo', );

    Which is called first, BUILD or the attribute_builders?

    The entire object instance is created and finalized before BUILD is called. When it gets to BUILD you can be sure you have a complete object (minus any non-initialized lazy attrs, etc).

    -stvn
Re: Moose and BUILD and 'ro' attributes
by tospo (Hermit) on Dec 15, 2010 at 10:11 UTC
    I'm not sure I completely understand the problem. Why can't this third attribute (parameter_string) not just be lazy-built from the other two? Could you give some code example?

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2024-04-24 02:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found