Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Moose constructor help

by Anonymous Monk
on Mar 13, 2014 at 13:54 UTC ( #1078180=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to use and understand Moose better, currently I use it for simple classes but am now stuck. I have some code that reads a json file, parses it and then returns a scalar with the decoded contents.
use JSON; open FH, "< myfile.json" or die $!; my $contents = <FH>; close FH; my $results = decode_json($contents);

My problem is that I wish to include the defining of the $results value in the class constructor, or possibly as a class method.Unfortunately I can't work out how to do this within Moose.

Can anyone help me?

Replies are listed 'Best First'.
Re: Moose constructor help
by kennethk (Abbot) on Mar 13, 2014 at 15:23 UTC
    You can do that using a default; if I assume you want $results to be a function of $contents, it might look like (untested):
    use Moose; use JSON; has content => isa => 'Str', is => 'ro', required=> 1, ; has results => isa => 'Str', is => 'ro', default => sub { decode_json($_[0]->content) }, ;
    There are a lot of variations how that would look depending on what you actually intend to do. See Default and builder methods in Moose::Manual::Attributes for more details.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      I'm not sure why you would need this in the constructor, but altering a little the example from kennethk, this is how I would do it:

      use Moose; use JSON; has content => ( isa => 'Str', is => 'ro', required=> 1, ); has results => ( isa => 'Str', is => 'ro', lazy => 1, builder => '_build_results', ); sub _build_results { my $self = shift; return decode_json($self->content); }

      With lazy and builder, the results attribute will be populated only when needed, only when you call $obj->results()

      Note: the builder method has access to $self, the reference to the instance, because it is called AFTER the instance is created, however, in kennethk's example, I don't think the default sub has access to $self or in this case $_[0]* because the default sub is executed WHILE the instance is being created, therefore, the reference is not yet available.

      * In a method, $_[0] contains the reference to the instance, same as if you do my $self = shift; or my $self = shift(@_); or my $self = $_[0];. I may be mistaking but I've had problems with this before and since then, I use lazy attributes with a builder method.

      A for will get you from A to Z; a while will get you everywhere.
Re: Moose constructor help
by Anonymous Monk on Mar 14, 2014 at 02:40 UTC
    Generally, a constructor should not "do" anything other than to perform base initialization on the object ... i.e. when "undef" is not enough. Default-methods in this case are probably just the ticket. Otherwise consider defining some sort of "init" method (of your own devising) which you call, just out of habit, after creating the object.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1078180]
Front-paged by Arunbear
Jar. Jar!...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (4)
As of 2018-05-25 02:21 GMT
Find Nodes?
    Voting Booth?