in reply to Re^3: Moose Attribute Default Dependency
in thread Moose Attribute Default Dependency

I went away and now I'm back ...

I read up on predicate, clearer and trigger attribute options and have revised the code. Though it bombs with the following error:

Can't call method "Dbase" on an undefined value at pizzle.pm line 29.
Compilation failed in require at test_pizzle.pl line 4.

Let me know if you have any further comments, before I begin to start to hit head here
XXXXXXXXXXXX
XXXXXXXXXXXX
XXXXXXXXXXXX
XXXXXXXXXXXX
XXXXXXXXXXXX
XXXXXXXXXXXX

package pizzle; use Moose; my $self; # Package Attributes has 'class_ver' => ( is => 'rw', isa => 'Str', default => '10.5.1' ); # Required Attributes has 'site' => ( is => 'rw', isa => 'Str', required => 1 ); # Directory Attributes has 'Dbase' => ( is => 'rw', isa => 'Str', default => '/willy/wonka', lazy => 1, predicate => 'has_Dbase' ); has 'Dbin' => ( is => 'rw', isa => 'Str', default => $self->{Dbase}.'/come/on/now', lazy => 1, predicate => 'has_Dbin' );

More directory attributes ...

# Diagnostic Attributes has 'diagCCS' => ( is => 'rw', isa => 'Str', lazy => 1, builder => '_build_diagCCS', predicate => 'has_diagCCS' ); has 'diagCFR' => ( is => 'rw', isa => 'Str', lazy => 1, builder => '_build_diagCFR', predicate => 'has_diagCFR' );

More diagnostic attributes ...

# Diagnostic Builders sub _build_diagCCS { my $self = shift; return `"$self->{Dbin}"/GetParameter "$self->{Fverbose}" 1 1 0 1`; } sub _build_diagCFR { my $self = shift; return `"$self->{Dbin}"/GetParameter "$self->{Fverbose}" 2 1 7 1`; }

More diagnostic builders ...

# Methods sub CleanDproc { my $self = shift; unlink $self->{Dproc}.'LLUVToCombine.list'; unlink $self->{Dproc}.'MergeTotalsInfo.ctf'; unlink $self->{Dproc}.'XYUVToCombine.list'; unlink $self->{Dproc}.'TotalProcessed.txt'; unlink $self->{Dproc}.'TotalTime.txt'; unlink $self->{Dproc}.'TotalOutput.txt'; unlink $self->{Dproc}.'Tot_XXXX_00_00_00_0000.tv'; unlink $self->{Dproc}.'TotxXXXX_00_00_00_0000.tv'; } 1;

End of pizzle.pm

Then test_pizzle.pl

#!/usr/bin/perl use strict; use pizzle; my $keepgoing = 1; #infinite loop while ($keepgoing eq 1) { my $piz = pizzle->new( site => 'binky' ); $piz->DiagCCS; $piz->DiagCCG; if ($piz->DiagCCS) { $keepgoing = 0; } }

Replies are listed 'Best First'.
Re^5: Moose Attribute Default Dependency
by chromatic (Archbishop) on Nov 13, 2013 at 01:55 UTC

    What do you expect this to do?

    my $self;

    What do you expect this to do?

                         default   => $self->{Dbase}.'/come/on/now',

    Improve your skills with Modern Perl: the free book.

      I expect

      my $self;

      will 'initialise' $self to allow

      default => $self->{Dbase}.'/come/on/now',

      it to be used.

      I now realise that this not OK and I must use builder.

        You don't have to use builder, this also works:

        has 'x' => ( is => 'rw', isa => 'Str', default => sub { my ($self) = @_; return $self->value; }, lazy => 1, );

        By the way, I should have said this earlier, I strongly second chromatic's suggestion!

        The answer to the question "Can we do this?" is always an emphatic "Yes!" Just give me enough time and money.
Re^5: Moose Attribute Default Dependency
by boftx (Deacon) on Nov 13, 2013 at 01:38 UTC

    Use a builder here instead of a default, $self doesn't exist yet when this is being executed:

    has 'Dbin' => ( is => 'rw', isa => 'Str', default => $self->{Dbase}.'/come/on/now', lazy => 1, predicate => 'has_Dbin' );

    Getting used to just how Moose builds an object, as well as the method modifiers, might lead to loss of hair at times, but groking this leads to solid code design with objects. On the plus side, Moose formalizes things to some extent that many of us had to improvise in the bad days.

    The answer to the question "Can we do this?" is always an emphatic "Yes!" Just give me enough time and money.

      Thanks boftx!

      I am still confused and must go away and do some more reading on Moose because I have taken your suggestion, but still do not get the results I am after. Below is complete code and here the new errors and output:

      Use of uninitialized value in concatenation (.) or string at cos_vectors.pm line 83.
      Use of uninitialized value in concatenation (.) or string at cos_vectors.pm line 83.
      Use of uninitialized value in concatenation (.) or string at cos_vectors.pm line 91.
      Use of uninitialized value in concatenation (.) or string at cos_vectors.pm line 87.
      Use of uninitialized value in concatenation (.) or string at cos_vectors.pm line 95.
      /Codar/SeaSonde/apps/combinetools/combineprocessing/CheckForCombine 0 bonc 1 "" /processings/processing_

      What's particularly annoying here is that it appears that one cannot build an attribute that is 'doubly' dependent -- i.e. look at

      sub _build_Dproc

      and notice that it depends on Ddata which in turn depends on Dbase. What's also frustrating that Dsite is not concatenating in

      sub _build_Dproc

      , which is not dependent on another attribute.
      Anyhow, thoroughly confused how to get this to work with Moose.

      package cos_vectors; use Moose; ###################################################################### +######### # Package Attributes has 'class_ver' => ( is => 'rw', isa => 'Str', default => '10.5.1' ); ###################################################################### +######### # Required Attributes has 'site' => ( is => 'rw', isa => 'Str', required => 1 ); ###################################################################### +######### # Directory Attributes has 'Dbase' => ( is => 'rw', isa => 'Str', default => '/Codar/SeaSonde', predicate => 'has_Dbase' ); has 'Dbin' => ( is => 'rw', isa => 'Str', builder => '_build_Dbin', predicate => 'has_Dbin' ); has 'Detc' => ( is => 'rw', isa => 'Str', builder => '_build_Detc', predicate => 'has_Detc' ); has 'Ddata' => ( is => 'rw', isa => 'Str', builder => '_build_Ddata', predicate => 'has_Ddata' ); has 'Dproc' => ( is => 'rw', isa => 'Str', builder => '_build_Dproc', predicate => 'has_Dproc' ); has 'Ddiag' => ( is => 'rw', isa => 'Str', builder => '_build_Ddiag', predicate => 'has_Ddiag' ); has 'Drad' => ( is => 'rw', isa => 'Str', builder => '_build_Drad', predicate => 'has_Drad' ); has 'Fopt' => ( is => 'rw', isa => 'Str', builder => '_build_Fopt', predicate => 'has_Fopt' ); has 'Fverbose' => ( is => 'rw', isa => 'Str', builder => '_build_Fverbose', predicate => 'has_Fverbose' ); ###################################################################### +######### # Directory Builders sub _build_Dbin { my $self = shift; return $self->{Dbase}.'/apps/combinetools/combineprocessing'; } sub _build_Detc { my $self = shift; return $self->{Dbase}.'/configs/combineconfigs'; } sub _build_Ddata { my $self = shift; return $self->{Dbase}.'/data'; } sub _build_Dproc { my $self = shift; return $self->{Ddata}.'/processings/processing_'.$self->{site}; } sub _build_Ddiag { my $self = shift; return $self->{Ddata}.'/diagnostics'; } sub _build_Drad { my $self = shift; return $self->{Ddata}.'/radialsites'; } sub _build_Fopt { my $self = shift; return $self->{Dbin}.'/combinesite.opt'; } sub _build_Fverbose { my $self = shift; return $self->{Dbin}.'/combineverbocity.txt'; } ###################################################################### +######### # Diagnostic Attributes has 'diagCCS' => ( is => 'rw', isa => 'Str', lazy => 1, builder => '_build_diagCCS', predicate => 'has_diagCCS' ); has 'diagCFR' => ( is => 'rw', isa => 'Str', lazy => 1, builder => '_build_diagCFR', predicate => 'has_diagCFR' ); has 'diagCCG' => ( is => 'rw', isa => 'Str', lazy => 1, builder => '_build_diagCCG', predicate => 'has_diagCCG' ); has 'diagRTC' => ( is => 'rw', isa => 'Str', lazy => 1, builder => '_build_diagRTC', predicate => 'has_diagRTC' ); has 'diagTA' => ( is => 'rw', isa => 'Str', lazy => 1, builder => '_build_diagTA', predicate => 'has_diagTA' ); has 'diagTD' => ( is => 'rw', isa => 'Str', lazy => 1, builder => '_build_diagTD', predicate => 'has_diagTD' ); ###################################################################### +######### # Diagnostic Builders sub _build_diagCCS { my $self = shift; return `$self->{Dbin}/GetParameter $self->{Fverbose} 1 1 0 1`; } sub _build_diagCFR { my $self = shift; return `$self->{Dbin}/GetParameter $self->{Fverbose} 2 1 7 1`; } sub _build_diagCCG { my $self = shift; return `$self->{Dbin}/GetParameter $self->{Fverbose} 3 1 2 1`; } sub _build_diagRTC { my $self = shift; return `$self->{Dbin}/GetParameter $self->{Fverbose} 4 1 2 1`; } sub _build_diagTA { my $self = shift; return `$self->{Dbin}/GetParameter $self->{Fverbose} 5 1 2 1`; } sub _build_diagTD { my $self = shift; return `$self->{Dbin}/GetParameter $self->{Fverbose} 6 1 1 1`; } ###################################################################### +######### # Methods sub clean_Dproc { my $self = shift; unlink $self->{Dproc}.'LLUVToCombine.list'; unlink $self->{Dproc}.'MergeTotalsInfo.ctf'; unlink $self->{Dproc}.'XYUVToCombine.list'; unlink $self->{Dproc}.'TotalProcessed.txt'; unlink $self->{Dproc}.'TotalTime.txt'; unlink $self->{Dproc}.'TotalOutput.txt'; unlink $self->{Dproc}.'Tot_XXXX_00_00_00_0000.tv'; unlink $self->{Dproc}.'TotxXXXX_00_00_00_0000.tv'; } 1;

      script

      #!/usr/bin/perl use strict; use cos_vectors; my $keepgoing = 1; #infinite loop while ($keepgoing eq 1) { my $vec = cos_vectors->new( site => 'bonc' ); print $vec->site." ".$vec->Fverbose."\n"; $vec->clean_Dproc; my $syscall = sprintf("%s/CheckForCombine 0 %s 1 \"\" %s",$vec->Db +in,$vec->site,$vec->Dproc); print $syscall."\n"; #system("$vec->{Dbin}/CheckForCombine 0 $vec->{site} 1 '' $vec->{D +proc}"); $keepgoing = 0; }

        Hmmm, start by using the attribute methods instead of the attribute elements as I mentioned earlier. On a side note, we need to get you more tools than just a hammer so everything doesn't look like a nail. :)

        A double-dependency as you put it is fine, but if you are not using the attribute methods you might well lose the ability to have it work as expected. Again, use $self->Dbase and not $self->{Dbase} (and similarly for Dbin and Ddata.) Start with that change and see what happens. Oh, one more thing I just noticed: you need to use the "lazy" property to take full advantage of a deferred build in the proper sequence.

        And maybe consider just what should be an attribute and what can be handled by a simple method call. I'm sure there are those here who would think that much of what you are doing can be done with just a very few attributes and the rest being methods, assuming that you really expect to default most (all?) of the derived directory names from Dbase and not provide values in the constructor. For example:

        # instead of this (which should have "lazy" set as well): has 'Dbin' => ( is => 'rw', isa => 'Str', builder => '_build_Dbin', predicate => 'has_Dbin' ); sub _build_Dbin { my $self = shift; return $self->{Dbase}.'/apps/combinetools/combineprocessing'; } # consider this instead if you will never set the value of Dbin # in the constructor. Note the use of $self->Dbase and not $self->{Dba +se}. sub Dbin { my $self = shift; return $self->Dbase.'/apps/combinetools/combineprocessing'; }
        The answer to the question "Can we do this?" is always an emphatic "Yes!" Just give me enough time and money.