/usr/local/CPAN/List-Enumerator/List/Enumerator/Array.pm


package List::Enumerator::Array;
use strict;
use warnings;

use base qw/List::Enumerator::Role/;
use overload
	'<<'  => \&push,
	'+'   => \&add,
	'@{}' => \&to_a,
	fallback => 1;

no warnings 'once';

__PACKAGE__->mk_accessors(qw/array index/);

sub BUILD {
	my ($self) = @_;
	$self->array([]) unless $self->array;
	$self->index(0);
}

sub _next {
	my ($self) = @_;

	my $i = $self->index;

	if ($i < @{$self->array}) {
		$self->index($i + 1);
		$self->array->[$i];
	} else {
		$self->stop;
	}
}

sub _rewind {
	my ($self) = @_;

	$self->index(0);
	$self;
}

sub to_a {
	my ($self) = @_;
	$self->array;
}
*as_list = \&to_a;

sub to_list {
	my ($self) = @_;
	@{$self->array};
}

sub push {
	my ($self, @args) = @_;
	CORE::push @{$self->array}, @args;
	$self;
}

sub add {
	my ($self, $array, $bool) = @_;
	$bool ? [ @$array, @{$self->array} ]
	      : [ @{$self->array}, @$array ];
}

sub unshift {
	my ($self, @args) = @_;
	CORE::unshift @{$self->array}, @args;
	$self;
}

sub prepend {
	my ($self, $args) = @_;
	CORE::unshift @{$self->array}, @$args;
	$self;
}

sub concat {
	my ($self, $args) = @_;
	CORE::push @{$self->array}, @$args;
	$self;
}
*append = \&concat;

sub shift {
	my ($self) = @_;
	CORE::shift @{$self->array};
}

sub pop {
	my ($self) = @_;
	CORE::pop @{$self->array};
}

sub delete {
	my ($self, $target, $block) = @_;
	my $ret = [];
	for (0 .. $#{$self->array}) {
		my $item = CORE::shift @{$self->array};
		if ($item eq $target) {
			CORE::push @$ret, $self->array->[$_];
		} else {
			CORE::push @{$self->array}, $item;
		}
	}
	@$ret ? $target
	      : ref($block) eq "CODE" ? $block->(local $_ = $target)
	                              : undef;
}

sub delete_if {
	my ($self, $block) = @_;
	my $ret = [];
	for my $index (0 .. $#{$self->array}) {
		my $item = CORE::shift @{$self->array};
		if ($block->(local $_ = $item)) {
			CORE::push @$ret, $item;
		} else {
			CORE::push @{$self->array}, $item;
		}
	}
	wantarray? @$ret : List::Enumerator::Array->new(array => $ret);
}

sub delete_at {
	my ($self, $index) = @_;
	return if $index > $#{$self->array};
	my $ret;
	for (0 .. $#{$self->array}) {
		my $item = CORE::shift @{$self->array};
		if ($_ == $index) {
			$ret = $item;
		} else {
			CORE::push @{$self->array}, $item;
		}
	}
	$ret;
}

# for performance
sub each {
	my ($self, $block) = @_;
	$self->rewind;


	if ($block) {
		eval {
			for (@{ $self->array }) {
				$block->(local $_ = $_);
			}
		}; if (Exception::Class->caught("StopIteration") ) { } else {
			my $e = Exception::Class->caught();
			ref $e ? $e->rethrow : die $e if $e;
		}
	}

	$self;
}

sub map {
	my ($self, $block) = @_;
	$self->rewind;
	my @ret;

	@ret = CORE::map({ $block->(local $_ = $_) } @{ $self->array });

	wantarray? @ret : List::Enumerator::Array->new(array => \@ret);
}


1;
__END__