Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

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

by nysus (Parson)
on Aug 28, 2019 at 19:21 UTC ( [id://11105179]=note: print w/replies, xml ) Need Help??


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

Ok, I spent a lot more time on this. I got it back to a one step process while using your idea to create iterator objects AND can do multiple iterators now. Woot!

sub AUTOLOAD { our $AUTOLOAD; my $s = shift; $AUTOLOAD =~ /.*::get(_next)*(_\w+)_files*$/ or croak "No such method: $AUTOLOAD"; my ($next, $type) = ($1, $2); # Handle edge case when get_next_file() method is called if (!$next && $type eq '_next') { $next = 1; $type = ''; } # return the requested list of files if (!$next) { my $attr = "${type}_files"; my @files = @{$s->{$attr}}; return @files; } # get a single file from an iterator if ($s->{"_iterator_$type"}) { my $file = $s->{"_iterator_$type"}->next_file; $s->{_last_iterator_file} = $file; undef $s->{"_iterator_$type"} if (!$file); return $file; } else { my @files = $type ? @{$s->{"${type}_files"}} : $s->get_files; return '' if !@files; my $class = ref($s) . '::Iterator'; $s->{"_iterator_$type"} = $class->new(@files); $s->{_last_iterator_file} = $s->{"_iterator_$type"}->selected_file +; return $s->{"_iterator_$type"}->selected_file; } } sub selected_file { my $s = shift; return $s->{_last_iterator_file}; }

Now I can do nested loops:

while ($fp->get_next_file) { print $fp->selected_file . "\n"; while ($fp->get_next_nonparseable_file) { print $fp->selected_file . "\n"; } }
Thanks so much for the pointers and getting me to think hard about this. Much appreciated!

$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^12: How to completely destroy class attributes with Test::Most?
by nysus (Parson) on Aug 28, 2019 at 19:46 UTC

    Building on your previous suggestion, now I'm thinking I could do something like this:

    $AUTOLOAD =~ /.*::(get|bundle)(_next)*(_\w+)_files*$/

    The bundle mode would also create an object that's just a list of files except you would perform operations on. So instead of:

    while ($s->get_next_blah_file) { $s->delete($s->selected_file); }
    You would just do:
    my $bundle = $s->bundle_blah_files; $bundle->delete;

    $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 key motivation for independent iterator objects is that they allow the program to have multiple iterators even on the same category by removing the need for the File::Collector object to track the iterators.

      These "bundles" look a lot like independent iterators, and you could easily introduce an ->all method that returns a special object like so:

      (in File::Collector::Iterator)

      sub all { my $self = shift; bless \ $self, 'File::Collector::Iterator::All'; } { package File::Collector::Iterator::All; sub AUTOLOAD { our $AUTOLOAD; my $self = shift; $$self->$AUTOLOAD(@_) while ($$self->next_file); } }

      This allows subclasses of File::Collector::Iterator to define their own "bundle actions" invokable as $iterator->all->$action. For example, a subclass that adds a delete action could contain simply:

      sub delete { unlink (shift)->selected_file }

        "The key motivation for independent iterator objects is that they allow the program to have multiple iterators even on the same category by removing the need for the File::Collector object to track the iterators."

        Yes, but there is a big convenience to having File::Collector track the iterators, isn't there? I can call $s->selected_file from anywhere and refer to the same file from any of the various class methods. I don't have to worry about passing the iterator objects around. Or am I missing something?

        $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

        I'll give a concrete example to make clear what I mean:

        package FileParser; use parent qw ( Dondley::WestfieldVote::FileCollector ); sub get_data { my $s = shift; return $s->get_obj_prop('data', 'raw_data', $_[0]); } package FileCollector; sub get_obj_prop { my $s = shift; my $obj = shift; my $prop = shift; my $file = shift || $s->selected_file; # grabs the current file in +iterator if (!$prop || !$obj || !$file) { $s->_croak ("Missing arguments to get_obj_prop method" . ' at ' . (caller(0))[1] . ', line ' . (caller(0))[2] ); } my $o = $obj . '_obj'; my $object = $s->{_files}{$file}{$o}; my $attr = "_$prop"; if (! exists $object->{$attr} ) { $s->croak ("Non-existent $obj object attribute requested: '$prop'" . ' at ' . (caller(0))[1] . ', line ' . (caller(0))[2] ); } my $value = $object->{$attr}; if (ref $value eq 'ARRAY') { return @$value; } else { return $value; } } package Data.pm sub new { my $class = shift; my $data = shift; my $obj = bless { _raw_data => $data, # raw Spreadsheet::Read object _stripped_data => undef, _num_rows => undef, _cols => undef, _num_cols => undef, _non_blank_cols => undef, _first_row => undef, }, $class; return $obj; } # And finally, in a file: my $fp = FileParser->new('some/dir'); while ($fp->next_parseable_file) { my $data = $fp->get_data; }

        This seems super convenient. If I'm not using an iterator, I can just pass a file to the get_data() method.

        $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

        That code for using the bundle did not work but this did:

        { package File::Collector::Iterator::All; sub AUTOLOAD { our $AUTOLOAD; my $self = shift; my @method = split /::/, $AUTOLOAD; my $method = pop @method; $$self->$method(@_) while ($$self->next); } }

        $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

Log In?
Username:
Password:

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

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

    No recent polls found