Perl-Sensitive Sunglasses | |
PerlMonks |
To make the factory more flexible, arguments may be passed to the factory to decide how to create the iterator. All state variables that are needed are declared and possibly initialized. A code reference in the same scope as the state variables is returned to the caller completing the transaction. Each time the code reference is executed, the state variables are updated and the next item is returned until the list is exhausted.sub gen_iterator { my @initial_info = @_; my ($current_state, $done); return sub { # code to calculate $next_state or $done; return undef if $done; return $current_state = $next_state; }; }
The basic usage of an iterator looks like:
my $next = gen_iterator( 42 ); while ( my $item = $next->() ) { print "$item\n"; }
my @DNA = qw/A C T G/; my $seq = gen_permutate(14, @DNA); while ( my $strand = $seq->() ) { print "$strand\n"; } sub gen_permutate { my ($max, @list) = @_; my @curr; return sub { if ( (join '', map { $list[ $_ ] } @curr) eq $list[ -1 ] x @cu +rr ) { @curr = (0) x (@curr + 1); } else { my $pos = @curr; while ( --$pos > -1 ) { ++$curr[ $pos ], last if $curr[ $pos ] < $#list; $curr[ $pos ] = 0; } } return undef if @curr > $max; return join '', map { $list[ $_ ] } @curr; }; }
my $start = $ARGV[0] || 999999; my $next_id = gen_id( $start ); print $next_id->(), "\n" for 1 .. 10; # Next 10 IDs sub gen_id { my $curr = shift; return sub { 0 while ! is_valid( ++$curr ); return $curr; }; } sub is_valid { my ($num, $chk) = (shift, ''); my $tot; for ( 0 .. length($num) - 1 ) { my $dig = substr($num, $_, 1); $_ % 2 ? ($chk .= $dig * 2) : ($tot += $dig); } $tot += $_ for split //, $chk; return $tot % 10 == 0 ? 1 : 0; }
Adding 1 state variable and an additional check would provide the ability to loop a user defined number of times.my $next_file = rotate( qw/FileA FileB FileC/ ); print $next_file->(), "\n" for 1 .. 10; sub rotate { my @list = @_; my $index = -1; return sub { $index++; $index = 0 if $index > $#list; return $list[ $index ]; }; }
while ( my $pass = $next_pw->() ) { if ( unlock( $pass ) ) { print "$pass\n"; last; } } sub fix_size_perm { my ($size, @list) = @_; my @curr = (0) x ($size - 1); push @curr, -1; return sub { if ( (join '', map { $list[ $_ ] } @curr) eq $list[ -1 ] x @cu +rr ) { @curr = (0) x (@curr + 1); } else { my $pos = @curr; while ( --$pos > -1 ) { ++$curr[ $pos ], last if $curr[ $pos ] < $#list; $curr[ $pos ] = 0; } } return undef if @curr > $size; return join '', map { $list[ $_ ] } @curr; }; } sub unlock { $_[0] eq 'john' }
Cheers - L~R
The tutorial has been updated to reflect suggestions from replies as well as the chatterbox. While the examples have been changed as well, I have retained the original code snippets in HTML comments if a reply referenced them.
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: How To: Make An Iterator
by Roy Johnson (Monsignor) on Apr 25, 2005 at 18:36 UTC | |
Re: How To: Make An Iterator
by tlm (Prior) on Apr 25, 2005 at 23:20 UTC | |
Re: How To: Make An Iterator
by Anonymous Monk on Apr 25, 2005 at 18:01 UTC | |
by Limbic~Region (Chancellor) on Apr 25, 2005 at 18:16 UTC | |
Re: How To: Make An Iterator
by kelan (Deacon) on Apr 25, 2005 at 21:13 UTC | |
Re: How To: Make An Iterator
by eric256 (Parson) on Apr 25, 2005 at 22:35 UTC | |
Re: How To: Make An Iterator
by ihb (Deacon) on Apr 26, 2005 at 14:17 UTC | |
Re: How To: Make An Iterator
by Anonymous Monk on Apr 17, 2006 at 19:24 UTC | |
by Limbic~Region (Chancellor) on Apr 17, 2006 at 22:42 UTC | |
by Anonymous Monk on Apr 20, 2006 at 00:09 UTC | |
by Limbic~Region (Chancellor) on Apr 20, 2006 at 12:24 UTC |