#!/usr/bin/perl
#
# eg16: grep for iterators example
#

use strict;
use warnings;
use Function::Parameters qw(:strict);

#
# my $it = upto( $min, $max ):
#	Make an iterator that counts from $min upwards
#	to $max and then fails..
#
fun upto( $n, $max )
{
	return fun {
		return undef if $n > $max;
		return $n++;
	};
}

#
# $it2 = grep_i( $op, $it ):
#	Equivalent of grep for iterators.
#	Given two coderefs ($op, an operator,
#	and $it, an existing iterator), return
#	a new iterator $it2 which returns only
#	the subset of values returned by the inner
#	iterator $it for which $op returns true.
#
fun grep_i( $op, $it ) :(&$)
{
	return fun {
		while( my $v = $it->() )
		{
			local $_ = $v;
			return $v if $op->($v);
		}
		return undef;
	};
}

my $lim = shift @ARGV || 10;
my $mod = shift @ARGV || 2;

my $c1 = upto( 1, $lim );
my $c2 = grep_i { $_ % $mod == 1 } $c1;

while( my $n = $c2->() ) { print "$n,"; }
print "\n";
