package Class::Iterator;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(imap igrep);

use Carp;

our $VERSION = "0.1";

sub new {
    my $proto = shift;
    my $class = ref($proto) || $proto;
    my $self  = {};
    bless ($self, $class);
    $self->generator(shift || sub { return sub { return } });
    $self->init;
    return $self;
}

sub init {
    my $self = shift;
    $self->iterator($self->generator->())
}


sub next {
    my $self = shift;
    return $self->iterator->();
}

sub AUTOLOAD {
    my ($self) = @_;
    my ($pack, $meth) =($AUTOLOAD =~ /^(.*)::(.*)$/);
    my @auth = qw(generator iterator);
    my %auth = map { $_ => 1 } @auth;
    unless ($auth{$meth}) {
	croak "Unknow method $meth";
    }
    
    my $code = sub {
	my $self = shift;
	my $arg = shift;
	if ($arg) {
	    $self->{"_$meth"} = $arg;
	} else {
	    return $self->{"_$meth"};
	}
    };
    
    *$AUTOLOAD = $code;
    goto &$AUTOLOAD;
	    
}

sub _imap {
    my ($rule, $generator) = @_;
    my $it = $generator->();
    return sub {
	return sub {
	    local $_ = $it->();
	    return unless defined $_;
	    return $rule->();
	}
    }
    
}

sub imap (&$) {
    my ($rule, $self) = @_;
    return $self->new(_imap($rule, $self->generator));
}


sub _igrep {
    my ($rule, $generator) = @_;
    my $it = $generator->();
    return sub {
	return sub {
	    while (defined(my $v = $it->())) {
		local $_ = $v;
		return $_ if $rule->();
	    }
	    return;
	}
    }
    
}


sub igrep (&$) {
    my ($rule, $self) = @_;
    return $self->new(_igrep($rule, $self->generator));
}



1;


__END__


# Below is stub documentation for your module. You better edit it!

=head1 NAME

Class::Iterator - Iterator class

=head1 SYNOPSIS

  use Class::Iterator;
  my $it = Class::Iterator->new(\&closure_generator);

  while (my $v = $it->next) { print "value : $v\n" }
  
  # use map like
  my $it2 = imap { ...some code with $_...} $it
  while (my $v = $it->next) { print "value : $v\n" }

  # use grep like
  my $it3 = imap { ...some code with $_...} $it
  while (my $v = $it->next) { print "value : $v\n" }


=head1 DESCRIPTION

Class::Iterator is a generic iterator object class. It use a closure an wrap 
into an object interface.

=over 4

=item new(\&closure_generator)

This is the constructor. The argument is a sub which look like
  sub closure_generator {
    my $private_data;
    return sub {
      # do something with $private_data
      # and return it
      return $private_data
    }
}

=item next

calling this method make one iteration. 

=item $o = imap { ... } $it

This a creator. It create a new iterator from an existant
iterator in the manner of map.

=item $o = igrep { ... } $it

This a creator. It create a new iterator from an existant
iterator in the manner of grep.


=back



=head1 AUTHOR

Robert Silve <robert@silve.net>

=cut
