Provided by: libiterator-simple-perl_0.07-3_all
NAME
Iterator::Simple - Simple iterator and utilities
SYNOPSIS
use Iterator::Simple; sub foo { my $max = shift; my $i = 0; iterator { return if $i > $max; $i++; } } my $iterator = foo(20); # yields 0,1,2, ..., 19, 20; $iterator = imap { $_ + 2 } $iterator; # yields 2,3,4,5, ... ,20,21,22 $iterator = igrep { $_ % 2 } $iterator; # yields 3,5,7,9, ... ,17,19,21 # iterable object $iterator = iter([qw(foo bar baz)]); # iterator from array ref $iterator = iter(IO::File->new($filename)); # iterator from GLOB # filters $iterator = ichain($itr1, $itr2); # chain iterators; $iterator = izip($itr1, $itr2); # zip iterators; $iterator = ienumerate $iterator; # add index; # general filter $iterator = ifilter $iterator, sub { return $_ if /^A/; return; } # how to iterate while(defined($_ = $iterator->())) { print; } while(defined($_ = $iterator->next)) { print; } while(<iterator>) { print; }
DESCRIPTION
Iterator::Simple is yet another general-purpose iterator utilities. Rather simple, but powerful and fast iterator.
FUNCTIONS
Iterator::Simple doesn't export any functions by default. please import them like: use Iterator::Simple qw(iter list imap); For all functions: use Iterator::Simple qw(:all); iterator { CODE } Iterator constructor. CODE returns a value on each call, and if it is exhausted, returns undef. Therefore, you cannot yields undefined value as a meaning value. If you want, you could use Iterator module which can do that. Generally, you can implement iterator as a closure like: use Iterator::Simple qw(iterator); sub fibonacci { my($s1, $s2, $max) = @_; iterator { my $rv; ($rv, $s1, $s2) = ($s1, $s2, $s1 + $s2); return if $rv > $max; return $rv; } } my $iterator = fiboacci(1, 1, 1000); You can iterate it in several ways: • just call it while(defined($_ = $iterator->())) { print "$_\n"; } • "next" method while(defined($_ = $iterator->next)) { print "$_\n"; } • <> operator while(<$iterator>) { print "$_\n"; } is_iterator($object) If $object is an iterator created by Iterator::Simple, returns true. False otherwise. iter($object) This function auto detects what $object is, and automatically turns it into an iterator. Supported objects are: • Iterator made with Iterator::Simple. • Object that implements "__iter__" method. • Object that overloads '<>' or has "next" method. • Object that overloads '&{}'.(as iterator function.) • Object that overloads '@{}'.(with "iarray()") • ARRAY reference. ("iarray()") • CODE reference. (as iterator function.) • GLOB reference. • nothing ("iter()".) (empty iterator.) If it fails to convert, runtime error. is_iterable($object) return true if $object can be converted with "iter($object)" list($object) This function converts $object into single array referece. • ARRAY reference. • GLOB reference. • Iterator made with Iterator::Simple. • Object that overloads '@{}' operator. • Object that implements '__iter__' method. • Object that overloads '<>' operator or has "next" method. • nothing (i.e. list() returns []); If it fails to convert, runtime error. Note that after "list($iterator)", that iterator is not usable any more. imap { CODE } $iterable This is the iterator version of "map". Returns an iterator which yields the value from source iterator modified by CODE. igrep { CODE } $iterable This is the iterator version of "grep". Returns an iterator which yields the value from source iterator only when CODE returns true value. iflatten $iterable When $iterable yields another iterator, iterate it first. $subitr = iter([10, 11,12]); $source = iter([ 1, 2, $subitr, 4]); $flattened = iflatten $source; # yields 1, 2, 10, 11, 12, 4. ifilter $iterable, sub{ CODE } This is the combination of imap, igrep, iflatten. it supports modify (imap) , skip (igrep), and inflate (iflatten). but it should be faster than combination of them. For example: $combination = iflatten imap { $_ eq 'baz' ? iter(['whoa', 'who']) : ":$_:" } igrep { $_ ne 'bar' } iter [ 'foo', 'bar', 'baz', 'fiz' ]; $itr = iter [ 'foo', 'bar', 'baz', 'fiz' ]; $filterd = ifilter $itr, sub { return if $_ eq 'bar'; #skip return iter(['whoa', 'who']) if $_ eq 'baz'; #inflate return ":$_:"; # modify }; Both of them will yields ':foo:', 'whoa', 'who', ':fiz:'. ichain($iterable, $iterable2, ...) This function returns an iterator which chains one or more iterators. Iterates each iterables in order as is, until each iterables are exhausted. Example: $itr1 = iter(['foo', 'bar', 'baz']); $itr2 = iter(['hoge', 'hage']); $chained = ichain($itr1, $itr2); # yields 'foo', 'bar', 'baz', 'hoge', 'hage'. ienumerate($iterable) This function returns an iterator yields like: $ary = iter(['foo', 'bar', 'baz', ... ]); $iter = ienumerate $ary; # yields [0, 'foo'], [1, 'bar'], [2, 'baz'], ... izip($iterable, $iterable2, ...); Accepts one or more iterables, returns an iterator like: $animals = iter(['dogs', 'cats', 'pigs']); $says = iter(['bowwow', 'mew', 'oink']); $zipped = izip($animals, $says); # yields ['dogs','bowwow'], ['cats','mew'], ['pigs', 'oink']. Note that when one of source iterables is exhausted, zipped iterator will be exhausted also. islice($iterable, $start, $end, $step) Same as islice of itertools in Python. If $end is undef or negative value, it iterates source until it is exhausted. $step defaults to 1. 0 or negative step value is prohibited. $iter = iter([0,1,2,3,4,5,6,7,8,9,10,11,12]); $sliced = islice($iter, 3, 13, 2); # yields 3, 5, 7, 9, 11. ihead($count, $iterable) islice($iterable, 0, $count, 1); iskip($count, $iterable) islice($iterable, $count, undef, 1); iarray($arrayref); Turns array reference into an iterator. Used in "iter($arrayref)". You do not have to use this function directly, because "iter($arrayref)" is sufficient.
OO INTERFACE
Iterator used in Iterator::Simple is just a code reference blessed in Iterator::Simple::Iterator. This class implements several method and overloads some operators. Itrator::Simple::Iterator->new($coderef) Just bless $coderef in Iterator::Simple::Iterator and returns it. $iterator->next Call underlying code. $iterator->__iter__ Returns self. You don't need to use this. Overloaded operators. • Read filehandle operator '<>' Overloading '<>' makes this possible like: print while <$iterator>; • Pipe.. bit_OR? .. No, pipe! $iterator | $coderef1 | $coderef2; is equivalent to: $iterator->filter($coderef1)->filter($coderef2); is equivalent to: ifilter(ifilter($iterator, $coderef1), $coderef2); $iterator->filter($coderef) $iterator->flatten() $iterator->chain($another, ..) $iterator->zip($another, ..) $iterator->enumerate() $iterator->slice($start, $end, $step) $iterator->head($count) $iterator->skip($count) For example, $iterator->flatten() is equivalent to "iflatten $iterator".
TIPS
All iterator transformation function calls "iter" function on all source iterables. So you can pass just array reference, GLOB ref, etc. These examples completely do the right thing: imap { $_ + 2 } [1, 2, 3, ... ]; ienumerate(\*STDIN); # DBIx::Class::ResultSet has 'next' method. ifilter $dbic_resultset, sub {CODE}; You can implement "__iter__" method on your objects in your application. By doing that, your object will be Iterator::Simple friendly :). Note that "__iter__" method must return an iterator.
Why Not Iterator.pm
There is another iterator module in CPAN, named Iterator and Iterator::Util made by Eric J. Roode that is great solution. Why yet another iterator module? The answer is *Speed*. You use iterator because you have too many data to manipulate in memory, therefore iterator could be called thousands of times, speed is important. For this simple example: use Iterator::Util qw(iarray imap igrep); for(1 .. 100) { my $itr = igrep { $_ % 2 } imap { $_ + 2 } iarray([1 .. 1000]); my @result; while($itr->isnt_exhausted) { push @result, $itr->value; } } meanwhile: use Iterator::Simple qw(iarray imap igrep); for(1 .. 100) { my $itr = igrep { $_ % 2 } imap { $_ + 2 } iarray([1 .. 1000]); my @result; while(defined($_ = $itr->())) { push @result, $_; } } Iterator::Simple is about ten times faster! That is natural because Iterator::Simple iterator is just a code reference, while Iterator.pm iterator is full featured class instance. But Iterator::Simple is sufficient for usual demands. One of most downside of Iterator::Simple is, you cannot yields undef value as a meaning value, because Iterator::Simple thinks it as a exhausted sign. If you need to do that, you have to yield something which represents undef value. Also, Iterator::Simple cannot determine iterator is exhausted until next iteration, while Iterator.pm has 'is(nt)_exhausted' method which is useful in some situation.
AUTHOR
Rintaro Ishizaki <rintaro@cpan.org>
LICENSE
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
SEE ALSO
• Iterator - Feature rich another iterator class. • Iterator::Util - Utilities which uses Iterator. Many of filter functions are from this module.