Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re^20: How to completely destroy class attributes with Test::Most?

by nysus (Parson)
on Aug 30, 2019 at 05:11 UTC ( [id://11105287]=note: print w/replies, xml ) Need Help??


in reply to Re^19: How to completely destroy class attributes with Test::Most?
in thread How to completely destroy class attributes with Test::Most?

Phew, ok, I think I really got it down good now. I did some more refinement of how things work, too. Here's what I got:

package File::Collector::DateAnalyzer ; use strict; use warnings; use Log::Log4perl::Shortcuts qw(:all); use File::Collector::DateAnalyzer::Iterator; use parent qw ( File::Collector ); sub add_resources { my $s = shift; $s->SUPER::add_resources(@_); $s->{files}{some_files} = File::Collector::DateAnalyzer::Ite +rator->new(); $s->{files}{other_files} = File::Collector::DateAnalyzer::Ite +rator->new(); $s->_test_blah; } sub _test_blah { my $s = shift; foreach my $file ($s->get_files) { $s->{files}{some_files}->add_file($s->{files}{all}{$file}); } } return 1; package File::Collector::DateAnalyzer::Iterator ; use strict; use warnings; use parent qw (File::Collector::Iterator); use Log::Log4perl::Shortcuts qw(:all); sub print_blah_names { my $s = shift; print $s->next->{short_path} . "\n\n"; } 1; package File::Collector::Iterator ; use strict; use warnings; use Carp; use Log::Log4perl::Shortcuts qw(:all); sub new { my $class = shift; bless [@_], $class; } sub next { my $s = shift; my $last = shift @$s; push @$s, $last; return $last; } sub add_file { my $s = shift; pop @$s; push @$s, shift; push @$s, ''; } sub print_short_names { my $s = shift; print $s->next->{short_path} . "\n"; } sub selected_file { my $s = shift; $s->[0]; } sub do { my $self = shift; bless \$self, 'File::Collector::Iterator::All'; } sub DESTROY { my $s = shift; $s->next while ($s->selected_file); } { package File::Collector::Iterator::All; use Log::Log4perl::Shortcuts qw(:all); sub AUTOLOAD { our $AUTOLOAD; my $self = shift; my @method = split /::/, $AUTOLOAD; my $method = pop @method; $$self->$method(@_) while ($$self->selected_file); $$self->next(@_); } }

A few notes:

Iterator is now a circular queue, terminated with an empty string.

Attributes of File::Collector subclasses are now iterators themselves. This let me get rid of the AUTOLOAD in File::Collector.

I restrucutred File::Collector->{files} as you suggested.

This simple test works:

{ my $da; # 1 lives_ok { $da = File::Collector::DateAnalyzer->new('t/test_data/many +_files'); } 'creates DateAnalyzer object'; $da->{files}{some_files}->do->print_blah_names; $da->{files}{some_files}->do->print_short_names; }

I will improve upon the do method calls so I don't have the ugly hashes in there and will use a simple AUTOLOAD so I can do $da->some_files->do->print_blah_names

How does it look to you?

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
$nysus = $PM . ' ' . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re^21: How to completely destroy class attributes with Test::Most?
by jcb (Parson) on Aug 30, 2019 at 23:54 UTC

    For a general-purpose File::Collector, I would expect support for multiple iterators even over the same category. ...

    And it just dawned on me: since Iterators are now circular (and presumably the empty string is not a valid file name, although it could be replaced with undef if someone tries this on a platform where it is valid and complains), all you need to support independent iterators for applications that want them is a ->clone method on iterators:

    sub clone { my $self = shift; bless [@$self], ref $self; }

    And you have made a change that is going to bite your users with infinite loops: the AUTOLOAD for ::Iterator::All should advance the iterator itself: $$self->$method(@_) while ($$self->next); or $$self->method(@) while (defined $$self->next); if you choose to make the end-of-set marker undef instead of an empty string. The method called by invoking ->do should not advance the iterator itself, but only use $self->selected_file.

      A problem with $$self->$method(@_) while ($$self->next); is that the first value gets thrown away. My change was a workaround to that until I figure out something better.

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

        The solution for that in Perl is just like C: do { $$self->$method(@_) } while ($$self->next);

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (1)
As of 2024-04-19 00:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found