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

While the mod//Moose docs are clear about not being able to pass arguments via super() they are not explicit about inner().

In my case, my superclass, is running a loop. I want to write a subclass that updates a progress bar based on what is happening in the parent. So my superclass would be:

for my $item (@item) { ++$i; inner($i); }
and then the subclass would take $i and the total record count to update the progress bar. The subclass would have all the graphics stuff and the superclass would be the raw data processing module.





The mantra of every experienced web application developer is the same: thou shalt separate business logic from display. Ironically, almost all template engines allow violation of this separation principle, which is the very impetus for HTML template engine development.

-- Terence Parr, "Enforcing Strict Model View Separation in Template Engines"

Replies are listed 'Best First'.
Re: You cannot pass args when calling inner() in Moose?
by kennethk (Abbot) on Jul 21, 2011 at 16:29 UTC
      But if you could pass arguments, you'd break the sub create {my $self = shift;... paradigm
      Yes, you have a point. I'm starting to see that Moose corrals you into keeping things in attributes instead of passing values around.
      for my $item (@item) { $self->i(++$i); inner(); }
      Ah nice. But there is a problem. There is not always an inner class... The superclass can be instatiated and run just fine if you dont plan to use perl/gtk to give GUI feedback on data processing. The inner call should only be called if ref $self ne __PACKAGE__

      Alternatively, I could always never run the superclass directly and have ::Gtk2 subclass as well as a ::PlainText subclass.



      The mantra of every experienced web application developer is the same: thou shalt separate business logic from display. Ironically, almost all template engines allow violation of this separation principle, which is the very impetus for HTML template engine development.

      -- Terence Parr, "Enforcing Strict Model View Separation in Template Engines"

      Arunbear's code below works, though I'm a little thrown.

      Actually, it doesn't. See my response.

      -stvn
Re: You cannot pass args when calling inner() in Moose?
by Arunbear (Prior) on Jul 21, 2011 at 16:51 UTC
    You can pass args e.g. (modified the doc example slightly)
    package Document::Page; use Moose; has 'body' => ( is => 'rw', isa => 'Str', default => sub {''} ); sub create { my $self = shift; my $arg = shift; warn $arg; $self->open_page; inner($arg); $self->close_page; } sub append_body { my ( $self, $appendage ) = @_; $self->body( $self->body . $appendage ); } sub open_page { (shift)->append_body('<page>') } sub close_page { (shift)->append_body('</page>') } package Document::PageWithHeadersAndFooters; use Moose; extends 'Document::Page'; augment 'create' => sub { my $self = shift; my $arg = shift; warn $arg; $self->create_header; inner($arg); $self->create_footer; }; sub create_header { (shift)->append_body('<header/>') } sub create_footer { (shift)->append_body('<footer/>') } package TPSReport; use Moose; extends 'Document::PageWithHeadersAndFooters'; augment 'create' => sub { my $self = shift; my $arg = shift; warn $arg; $self->create_tps_report; inner($arg); }; sub create_tps_report { (shift)->append_body('<report type="tps"/>'); } package main; # <page><header/><report type="tps"/><footer/></page> my $report_xml = TPSReport->new->create('food'); print "$report_xml\n";
    Aslo the definitions in Moose.pm look like this:
    sub super { # This check avoids a recursion loop - see # t/bugs/super_recursion.t return if defined $SUPER_PACKAGE && $SUPER_PACKAGE ne caller(); return unless $SUPER_BODY; $SUPER_BODY->(@SUPER_ARGS); } sub inner { my $pkg = caller(); our ( %INNER_BODY, %INNER_ARGS ); if ( my $body = $INNER_BODY{$pkg} ) { my @args = @{ $INNER_ARGS{$pkg} }; local $INNER_ARGS{$pkg}; local $INNER_BODY{$pkg}; return $body->(@args); } else { return; } }

      This is not actually working, it only appears to work because you are passing a value from @_ into inner(), which it already gets passed anyway. inner() does not accept arguments, same as super().

      -stvn
        Fair enough, thanks for clarifying that.
Re: You cannot pass args when calling inner() in Moose?
by Anonymous Monk on Jul 22, 2011 at 11:27 UTC
    Can't you use "around?"
      No, because the superclass method does things before and after the loop. The only thing that the GUI aspect does is update a progress bar during a loop. I settled on simply having an if-then within updateprogress
      sub updateprogress { my ($self) = @_; return unless $self->progressbar; my @frac = ($self->recordi, $self->recordcount); my $frac = frac(@frac); $self->progressbar->set_fraction($frac->num); $self->progressbar->set_text( sprintf '%d / %d', @frac); use Gtk2; while (Gtk2->events_pending) { Gtk2->main_iteration; } Gtk2::Gdk->flush; }
      sub manager { my ($Operation) = @_; my @row = $Operation->getnew; $Operation->log->debug( 'getnew rows:' . scalar(@row) ); $Operation->recordi(0); for my $row (@row) { $Operation->recordi( $Operation->recordi + 1 ); $Operation->log->debug( ' --- data --- ' . Dumper($row) ); $Operation->data($row); $Operation->process; $Operation->updateprogress; } }




      The mantra of every experienced web application developer is the same: thou shalt separate business logic from display. Ironically, almost all template engines allow violation of this separation principle, which is the very impetus for HTML template engine development.

      -- Terence Parr, "Enforcing Strict Model View Separation in Template Engines"