I want to fetch elements from a list that is stored inside a Moose class. The class knows how to populate that list itself. It's sort of like an iterator, except that I want to be able to reset the iterator, and start fetching the same elements from that list as if I hadn't already done so. I intend to call as follows:
while( my $slotlist = $class->get_next_slotlist ) {
# do something with $slotlist
}
Except that, as I said, I may want to reiterate over the same elements again at a later point:
$class->reset_slotlists;
while( my $slotlist = $class->get_next_slotlist ) {
# do something with $slotlist
}
I thought of designing the class along the lines of the following stripped-down (mock) version:
package List;
use Moose;
has '_data' => (
traits => [ 'Array' ],
is => 'ro',
predicate => 'has_data',
lazy => 1,
builder => '_build_data',
clearer => 'reset',
handles => {
next => 'shift',
},
);
sub _build_data { [ 'abc', 'def' ] }
package main;
use strict;
use warnings;
use Test::More;
use Test::Pretty;
my $list = List->new;
ok ! $list->has_data;
is $list->next, 'abc';
is $list->next, 'def';
is $list->next, undef;
is $list->next, undef;
$list->reset;
is $list->next, 'abc', 'Moose calls builder again after clearing';
is $list->next, 'def';
is $list->next, undef;
is $list->next, undef;
ok $list->has_data;
done_testing;
When I run this, Moose calls the builder again after the call to reset() (i.e., the clearer). My question is now: is this behaviour guaranteed? The documentation doesn't say.
(While typing this question, I also started wondering: do you think this is bad design? I like the iterator-like interface, very elegant on the calling side, and easy to implement. But is this very question a sign that the design isn't good?)