# 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:

• 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.

• 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.``````
``  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.

``  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->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>
{"ft_lang_label":"__label__en","ft_lang_prob":0.57202107,"math_prob":0.8838317,"size":8963,"snap":"2020-24-2020-29","text_gpt3_token_len":2509,"char_repetition_ratio":0.17926107,"word_repetition_ratio":0.07579102,"special_character_ratio":0.31473836,"punctuation_ratio":0.25589225,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9730036,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2020-07-12T14:04:29Z\",\"WARC-Record-ID\":\"<urn:uuid:d49948d8-6760-4875-b612-e4d5f795563c>\",\"Content-Length\":\"45306\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:de3f0ef8-0d59-4db6-8f87-ca4fbf4a9633>\",\"WARC-Concurrent-To\":\"<urn:uuid:971a9cdf-662e-4873-8a82-dda5124036c9>\",\"WARC-IP-Address\":\"199.232.66.217\",\"WARC-Target-URI\":\"http://web-stage.metacpan.org/pod/Iterator::Simple\",\"WARC-Payload-Digest\":\"sha1:HUWI5HRIRGDXURO5RHABN475R7JEAOGD\",\"WARC-Block-Digest\":\"sha1:N3O2HGTVPUFCD6FIJJF3OYID2OWVBYLT\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2020/CC-MAIN-2020-29/CC-MAIN-2020-29_segments_1593657138718.61_warc_CC-MAIN-20200712113546-20200712143546-00090.warc.gz\"}"}