.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Iterator::Simple 3pm" .TH Iterator::Simple 3pm "2019-10-20" "perl v5.30.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Iterator::Simple \- Simple iterator and utilities .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& 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() { \& print; \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Iterator::Simple is yet another general-purpose iterator utilities. .PP Rather simple, but powerful and fast iterator. .SH "FUNCTIONS" .IX Header "FUNCTIONS" Iterator::Simple doesn't export any functions by default. please import them like: .PP .Vb 1 \& use Iterator::Simple qw(iter list imap); .Ve .PP For all functions: .PP .Vb 1 \& use Iterator::Simple qw(:all); .Ve .IP "iterator { \s-1CODE\s0 }" 4 .IX Item "iterator { CODE }" Iterator constructor. \s-1CODE\s0 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. .Sp Generally, you can implement iterator as a closure like: .Sp .Vb 1 \& 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); .Ve .Sp You can iterate it in several ways: .RS 4 .IP "\(bu" 2 just call it .Sp .Vb 3 \& while(defined($_ = $iterator\->())) { \& print "$_\en"; \& } .Ve .IP "\(bu" 2 \&\f(CW\*(C`next\*(C'\fR method .Sp .Vb 3 \& while(defined($_ = $iterator\->next)) { \& print "$_\en"; \& } .Ve .IP "\(bu" 2 <> operator .Sp .Vb 3 \& while(<$iterator>) { \& print "$_\en"; \& } .Ve .RE .RS 4 .RE .IP "is_iterator($object)" 4 .IX Item "is_iterator($object)" If \f(CW$object\fR is an iterator created by Iterator::Simple, returns true. False otherwise. .IP "iter($object)" 4 .IX Item "iter($object)" This function auto detects what \f(CW$object\fR is, and automatically turns it into an iterator. Supported objects are: .RS 4 .IP "\(bu" 2 Iterator made with Iterator::Simple. .IP "\(bu" 2 Object that implements \f(CW\*(C`_\|_iter_\|_\*(C'\fR method. .IP "\(bu" 2 Object that overloads '<>' or has \f(CW\*(C`next\*(C'\fR method. .IP "\(bu" 2 Object that overloads '&{}'.(as iterator function.) .IP "\(bu" 2 Object that overloads '@{}'.(with \f(CW\*(C`iarray()\*(C'\fR) .IP "\(bu" 2 \&\s-1ARRAY\s0 reference. (\f(CW\*(C`iarray()\*(C'\fR) .IP "\(bu" 2 \&\s-1CODE\s0 reference. (as iterator function.) .IP "\(bu" 2 \&\s-1GLOB\s0 reference. .IP "\(bu" 2 nothing (\f(CW\*(C`iter()\*(C'\fR.) (empty iterator.) .RE .RS 4 .Sp If it fails to convert, runtime error. .RE .IP "is_iterable($object)" 4 .IX Item "is_iterable($object)" return true if \f(CW$object\fR can be converted with \f(CW\*(C`iter($object)\*(C'\fR .IP "list($object)" 4 .IX Item "list($object)" This function converts \f(CW$object\fR into single array referece. .RS 4 .IP "\(bu" 2 \&\s-1ARRAY\s0 reference. .IP "\(bu" 2 \&\s-1GLOB\s0 reference. .IP "\(bu" 2 Iterator made with Iterator::Simple. .IP "\(bu" 2 Object that overloads '@{}' operator. .IP "\(bu" 2 Object that implements '_\|_iter_\|_' method. .IP "\(bu" 2 Object that overloads '<>' operator or has \f(CW\*(C`next\*(C'\fR method. .IP "\(bu" 2 nothing (i.e. \fBlist()\fR returns []); .RE .RS 4 .Sp If it fails to convert, runtime error. .Sp Note that after \f(CW\*(C`list($iterator)\*(C'\fR, that iterator is not usable any more. .RE .ie n .IP "imap { \s-1CODE\s0 } $iterable" 4 .el .IP "imap { \s-1CODE\s0 } \f(CW$iterable\fR" 4 .IX Item "imap { CODE } $iterable" This is the iterator version of \f(CW\*(C`map\*(C'\fR. Returns an iterator which yields the value from source iterator modified by \s-1CODE.\s0 .ie n .IP "igrep { \s-1CODE\s0 } $iterable" 4 .el .IP "igrep { \s-1CODE\s0 } \f(CW$iterable\fR" 4 .IX Item "igrep { CODE } $iterable" This is the iterator version of \f(CW\*(C`grep\*(C'\fR. Returns an iterator which yields the value from source iterator only when \s-1CODE\s0 returns true value. .ie n .IP "iflatten $iterable" 4 .el .IP "iflatten \f(CW$iterable\fR" 4 .IX Item "iflatten $iterable" When \f(CW$iterable\fR yields another iterator, iterate it first. .Sp .Vb 2 \& $subitr = iter([10, 11,12]); \& $source = iter([ 1, 2, $subitr, 4]); \& \& $flattened = iflatten $source; \& \& # yields 1, 2, 10, 11, 12, 4. .Ve .ie n .IP "ifilter $iterable, sub{ \s-1CODE\s0 }" 4 .el .IP "ifilter \f(CW$iterable\fR, sub{ \s-1CODE\s0 }" 4 .IX Item "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. .Sp For example: .Sp .Vb 4 \& $combination = iflatten \& imap { $_ eq \*(Aqbaz\*(Aq ? iter([\*(Aqwhoa\*(Aq, \*(Aqwho\*(Aq]) : ":$_:" } \& igrep { $_ ne \*(Aqbar\*(Aq } \& iter [ \*(Aqfoo\*(Aq, \*(Aqbar\*(Aq, \*(Aqbaz\*(Aq, \*(Aqfiz\*(Aq ]; \& \& $itr = iter [ \*(Aqfoo\*(Aq, \*(Aqbar\*(Aq, \*(Aqbaz\*(Aq, \*(Aqfiz\*(Aq ]; \& $filterd = ifilter $itr, sub { \& return if $_ eq \*(Aqbar\*(Aq; #skip \& return iter([\*(Aqwhoa\*(Aq, \*(Aqwho\*(Aq]) if $_ eq \*(Aqbaz\*(Aq; #inflate \& return ":$_:"; # modify \& }; .Ve .Sp Both of them will yields \f(CW\*(Aq:foo:\*(Aq, \*(Aqwhoa\*(Aq, \*(Aqwho\*(Aq, \*(Aq:fiz:\*(Aq\fR. .ie n .IP "ichain($iterable, $iterable2, ...)" 4 .el .IP "ichain($iterable, \f(CW$iterable2\fR, ...)" 4 .IX Item "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. .Sp Example: .Sp .Vb 2 \& $itr1 = iter([\*(Aqfoo\*(Aq, \*(Aqbar\*(Aq, \*(Aqbaz\*(Aq]); \& $itr2 = iter([\*(Aqhoge\*(Aq, \*(Aqhage\*(Aq]); \& \& $chained = ichain($itr1, $itr2); \& \& # yields \*(Aqfoo\*(Aq, \*(Aqbar\*(Aq, \*(Aqbaz\*(Aq, \*(Aqhoge\*(Aq, \*(Aqhage\*(Aq. .Ve .IP "ienumerate($iterable)" 4 .IX Item "ienumerate($iterable)" This function returns an iterator yields like: .Sp .Vb 1 \& $ary = iter([\*(Aqfoo\*(Aq, \*(Aqbar\*(Aq, \*(Aqbaz\*(Aq, ... ]); \& \& $iter = ienumerate $ary; \& \& # yields [0, \*(Aqfoo\*(Aq], [1, \*(Aqbar\*(Aq], [2, \*(Aqbaz\*(Aq], ... .Ve .ie n .IP "izip($iterable, $iterable2, ...);" 4 .el .IP "izip($iterable, \f(CW$iterable2\fR, ...);" 4 .IX Item "izip($iterable, $iterable2, ...);" Accepts one or more iterables, returns an iterator like: .Sp .Vb 2 \& $animals = iter([\*(Aqdogs\*(Aq, \*(Aqcats\*(Aq, \*(Aqpigs\*(Aq]); \& $says = iter([\*(Aqbowwow\*(Aq, \*(Aqmew\*(Aq, \*(Aqoink\*(Aq]); \& \& $zipped = izip($animals, $says); \& \& # yields [\*(Aqdogs\*(Aq,\*(Aqbowwow\*(Aq], [\*(Aqcats\*(Aq,\*(Aqmew\*(Aq], [\*(Aqpigs\*(Aq, \*(Aqoink\*(Aq]. .Ve .Sp Note that when one of source iterables is exhausted, zipped iterator will be exhausted also. .ie n .IP "islice($iterable, $start, $end, $step)" 4 .el .IP "islice($iterable, \f(CW$start\fR, \f(CW$end\fR, \f(CW$step\fR)" 4 .IX Item "islice($iterable, $start, $end, $step)" Same as islice of itertools in Python. If \f(CW$end\fR is undef or negative value, it iterates source until it is exhausted. \&\f(CW$step\fR defaults to 1. 0 or negative step value is prohibited. .Sp .Vb 1 \& $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. .Ve .ie n .IP "ihead($count, $iterable)" 4 .el .IP "ihead($count, \f(CW$iterable\fR)" 4 .IX Item "ihead($count, $iterable)" .Vb 1 \& islice($iterable, 0, $count, 1); .Ve .ie n .IP "iskip($count, $iterable)" 4 .el .IP "iskip($count, \f(CW$iterable\fR)" 4 .IX Item "iskip($count, $iterable)" .Vb 1 \& islice($iterable, $count, undef, 1); .Ve .IP "iarray($arrayref);" 4 .IX Item "iarray($arrayref);" Turns array reference into an iterator. Used in \f(CW\*(C`iter($arrayref)\*(C'\fR. You do not have to use this function directly, because \&\f(CW\*(C`iter($arrayref)\*(C'\fR is sufficient. .SH "OO INTERFACE" .IX Header "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. .IP "Itrator::Simple::Iterator\->new($coderef)" 4 .IX Item "Itrator::Simple::Iterator->new($coderef)" Just bless \f(CW$coderef\fR in Iterator::Simple::Iterator and returns it. .ie n .IP "$iterator\->next" 4 .el .IP "\f(CW$iterator\fR\->next" 4 .IX Item "$iterator->next" Call underlying code. .ie n .IP "$iterator\->_\|_iter_\|_" 4 .el .IP "\f(CW$iterator\fR\->_\|_iter_\|_" 4 .IX Item "$iterator->__iter__" Returns self. You don't need to use this. .IP "Overloaded operators." 4 .IX Item "Overloaded operators." .RS 4 .PD 0 .IP "\(bu" 2 .PD Read filehandle operator '<>' .Sp Overloading '<>' makes this possible like: .Sp .Vb 1 \& print while <$iterator>; .Ve .IP "\(bu" 2 Pipe.. bit_OR? .. No, pipe! .Sp .Vb 1 \& $iterator | $coderef1 | $coderef2; .Ve .Sp is equivalent to: .Sp .Vb 1 \& $iterator\->filter($coderef1)\->filter($coderef2); .Ve .Sp is equivalent to: .Sp .Vb 1 \& ifilter(ifilter($iterator, $coderef1), $coderef2); .Ve .RE .RS 4 .RE .ie n .IP "$iterator\->filter($coderef)" 4 .el .IP "\f(CW$iterator\fR\->filter($coderef)" 4 .IX Item "$iterator->filter($coderef)" .PD 0 .ie n .IP "$iterator\->\fBflatten()\fR" 4 .el .IP "\f(CW$iterator\fR\->\fBflatten()\fR" 4 .IX Item "$iterator->flatten()" .ie n .IP "$iterator\->chain($another, ..)" 4 .el .IP "\f(CW$iterator\fR\->chain($another, ..)" 4 .IX Item "$iterator->chain($another, ..)" .ie n .IP "$iterator\->zip($another, ..)" 4 .el .IP "\f(CW$iterator\fR\->zip($another, ..)" 4 .IX Item "$iterator->zip($another, ..)" .ie n .IP "$iterator\->\fBenumerate()\fR" 4 .el .IP "\f(CW$iterator\fR\->\fBenumerate()\fR" 4 .IX Item "$iterator->enumerate()" .ie n .IP "$iterator\->slice($start, $end, $step)" 4 .el .IP "\f(CW$iterator\fR\->slice($start, \f(CW$end\fR, \f(CW$step\fR)" 4 .IX Item "$iterator->slice($start, $end, $step)" .ie n .IP "$iterator\->head($count)" 4 .el .IP "\f(CW$iterator\fR\->head($count)" 4 .IX Item "$iterator->head($count)" .ie n .IP "$iterator\->skip($count)" 4 .el .IP "\f(CW$iterator\fR\->skip($count)" 4 .IX Item "$iterator->skip($count)" .PD For example, \f(CW$iterator\fR\->\fBflatten()\fR is equivalent to \&\f(CW\*(C`iflatten $iterator\*(C'\fR. .SH "TIPS" .IX Header "TIPS" All iterator transformation function calls \f(CW\*(C`iter\*(C'\fR function on all source iterables. So you can pass just array reference, \s-1GLOB\s0 ref, etc. .PP These examples completely do the right thing: .PP .Vb 2 \& imap { $_ + 2 } [1, 2, 3, ... ]; \& ienumerate(\e*STDIN); \& \& # DBIx::Class::ResultSet has \*(Aqnext\*(Aq method. \& ifilter $dbic_resultset, sub {CODE}; .Ve .PP You can implement \f(CW\*(C`_\|_iter_\|_\*(C'\fR method on your objects in your application. By doing that, your object will be Iterator::Simple friendly :). .PP Note that \f(CW\*(C`_\|_iter_\|_\*(C'\fR method must return an iterator. .SH "Why Not Iterator.pm" .IX Header "Why Not Iterator.pm" There is another iterator module in \s-1CPAN,\s0 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. .PP For this simple example: .PP .Vb 1 \& 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; \& } \& } .Ve .PP meanwhile: .PP .Vb 1 \& 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, $_; \& } \& } .Ve .PP Iterator::Simple is about ten times faster! .PP 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. .PP 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. .PP 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. .SH "AUTHOR" .IX Header "AUTHOR" Rintaro Ishizaki .SH "LICENSE" .IX Header "LICENSE" This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" .IP "\(bu" 2 Iterator \- Feature rich another iterator class. .IP "\(bu" 2 Iterator::Util \- Utilities which uses Iterator. Many of filter functions are from this module.