Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
Iterator::Simple(3)   User Contributed Perl Documentation  Iterator::Simple(3)

       Iterator::Simple	- Simple iterator and utilities

	 use Iterator::Simple;

	 sub foo {
	   my $max = shift;
	   my $i = 0;
	   iterator {
	     return if $i > $max;

	 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/;

	 # how to iterate
	 while(defined($_ = $iterator->())) {

	 while(defined($_ = $iterator->next)) {

	 while(<iterator>) {

       Iterator::Simple	is yet another general-purpose iterator	utilities.

       Rather simple, but powerful and fast iterator.

       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:

	   o just call it

	       while(defined($_	= $iterator->())) {
		 print "$_\n";

	   o "next" method

	       while(defined($_	= $iterator->next)) {
		 print "$_\n";

	   o <>	operator

	       while(<$iterator>) {
		 print "$_\n";

	   If $object is an iterator created by	Iterator::Simple, returns
	   true.  False	otherwise.

	   This	function auto detects what $object is, and automatically turns
	   it into an iterator.	Supported objects are:

	   o Iterator made with	Iterator::Simple.

	   o Object that implements "__iter__" method.

	   o Object that overloads '<>'	or has "next" method.

	   o Object that overloads '&{}'.(as iterator function.)

	   o Object that overloads '@{}'.(with "iarray()")

	   o ARRAY reference. ("iarray()")

	   o CODE reference. (as iterator function.)

	   o GLOB reference.

	   o nothing ("iter()".) (empty	iterator.)

	   If it fails to convert, runtime error.

	   return true if $object can be converted with	"iter($object)"

	   This	function converts $object into single array referece.

	   o ARRAY reference.

	   o GLOB reference.

	   o Iterator made with	Iterator::Simple.

	   o Object that overloads '@{}' operator.

	   o Object that implements '__iter__' method.

	   o Object that overloads '<>'	operator or has	"next" method.

	   o nothing (i.e. list() returns []);

	   If it fails to convert, runtime error.

	   Note	that after "list($iterator)", that iterator is not usable any

       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

       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.


	     $itr1 = iter(['foo', 'bar', 'baz']);
	     $itr2 = iter(['hoge', 'hage']);

	     $chained =	ichain($itr1, $itr2);

	     # yields 'foo', 'bar', 'baz', 'hoge', 'hage'.

	   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);

	   Turns array reference into an iterator. Used	in "iter($arrayref)".
	   You do not have to use this function	directly, because
	   "iter($arrayref)" is	sufficient.

       Iterator	used in	Iterator::Simple is just a code	reference blessed in
       Iterator::Simple::Iterator. This	class implements several method	and
       overloads some operators.

	   Just	bless $coderef in Iterator::Simple::Iterator and returns it.

	   Call	underlying code.

	   Returns self. You don't need	to use this.

       Overloaded operators.
	   o Read filehandle operator '<>'

	     Overloading '<>' makes this possible like:

	       print while <$iterator>;

	   o Pipe.. bit_OR? .. No, pipe!

	       $iterator | $coderef1 | $coderef2;

	     is	equivalent to:


	     is	equivalent to:

	       ifilter(ifilter($iterator, $coderef1), $coderef2);

       $iterator->chain($another, ..)
       $iterator->zip($another,	..)
       $iterator->slice($start,	$end, $step)
	   For example,	$iterator->flatten() is	equivalent to "iflatten

       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, ... ];

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


	 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 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 has 'is(nt)_exhausted'	method which
       is useful in some situation.

       Rintaro Ishizaki	<>

       This library is free software; you can redistribute it and/or modify it
       under the same terms as Perl itself.

       o Iterator - Feature rich another iterator class.

       o Iterator::Util	- Utilities which uses Iterator. Many of filter
	 functions are from this module.

perl v5.32.1			  2017-12-07		   Iterator::Simple(3)


Want to link to this manual page? Use this URL:

home | help