OK, here's what I got for now. I added some efficiency to it and it now throws an error if the user tries to invoke a second iterator before the queue is empty. If I need to nest loops over files, I can use a conventional for loop for that, I guess. Thanks again for the guidance on this.
# Returns files from a method as determined by the "type" in the metho
+d's name:
# get_type_files() returns a list of files found in an obj attribute
# get_next_type_file() places the list of files into a queue for itera
+tion
#
# Examples:
# $s->get_old_files;
# $s->get_next_new_file;
sub AUTOLOAD {
our $AUTOLOAD;
my $s = shift;
$AUTOLOAD =~ /.*::get(_next)*(_\w+)_files*$/ or
croak "No such method: $AUTOLOAD";
my ($next, $type) = ($1, $2);
# Don't stomp on an already existing iterator
my $last = $s->{_last_next_req};
if ($next && $last && ($last ne $type) && @{$s->{_file_queue}}) {
croak "File queue not empty, cannot create iterator. Aborting.";
}
$s->{_last_next_req} = $type if $next;
# Don't re-fetch files if we already have files in queue
if ($next && @{$s->{_file_queue}}) {
return $s->get_next_file;
}
# Get the files and return appropriate file(s) based on method calle
+d
my $attr = "${type}_files";
my @files = @{$s->{$attr}};
return @files if !@files || !$next;
return $s->get_next_file(@files);
}
sub new {
my $class = shift;
my $s = bless { _files => {},
_target_repo => '',
_selected_file => '',
_common_dir => '',
_last_next_req => '',
_file_queue => []}, $class;
$s->add_resources(@_);
return $s;
}
sub get_next_file {
my $s = shift;
if (!$s->{_selected_file}) {
my @files = @_ ? @_ : $s->get_files;
$s->{_file_queue} = \@files;
}
my $next_file = shift @{$s->{_file_queue}};
$s->{_selected_file} = $next_file;
return $next_file;
}