C:\test>p1
perl> sub getIter{ my ($s,$e,$ref)=@_; $e=$#$ref if $e==-1; return sub
+ { $s<=$e ? $ref->[$s++] : (); }}
perl> @a = 1 .. 1000000
perl> $iter = getIter 500000, 500005, \@a
perl> print while $_ = $iter->()
500001500002500003500004500005500006
perl>
Which, whilst it proved that the basic idea worked, wasn't very palitable. So, being lazy, I C&P'd from the screen and modified it in the edit box. Bad move.
BTW. You forgot to mention that the condition needs to be "<" not "<=" :^).
However, making the above code into a normal program like so
#! perl -slw
use strict;
sub getIter{
my ($start, $end, $aryRef) = @_;
$end = $#$aryRef if $end == -1;
return sub {
return $aryRef->[$start++] if $start < $end;
();
}
}
my @a = 1 .. 1000000;
my $iter = getIter 500000, 500005, \@a;
print while $_ = $iter->();
__END__
500001
500002
500003
500004
500005
Does produce the output I indicated.
You can take it a step further step further using *_.
#! perl -slw
use strict;
sub getIter{
my ($s, $e, $ref)=@_;
$e = $#$ref if $e == -1;
return sub {
($s < $e) ? *_ = \$ref->[$s++] : return;
}
}
my @a = 1 .. 1000000;
my $iter = getIter 500000, 500005, \@a;
print while $iter->();
$iter = getIter 500000, 500005, \@a;
$_ = 'modified' while $iter->();
$iter = getIter 500000, 500005, \@a;
print while $iter->();
__END__
C:\test>227478
500001
500002
500003
500004
500005
modified
modified
modified
modified
modified
C:\test>
Which does alais the array being iterated and allow write operations. However, it stomps on $_ which a for loop doesn't.
#! perl -slw
use strict;
$_ = 'some value';
print;
for (1 .. 10) { print; }
print;
__END__
C:\test>temp
some value
1
2
3
4
5
6
7
8
9
10
some value
C:\test>
I am unaware of any way of emulating perl's behaviour in localising $_ in your own iterators unfortunately.
You can wrap the use of the iterator in a bare block and localise $_ for the duration of the scope of use, which is effectively what you are doing, though the for loop block provides a naturally convienient scope rather than having to create one artificially.
With regard to the other two matters.
Why
while ( ($_) = $iter->() ) { ...
rather than
while ($_ = $iter-() ) { ...?
As for the range operator building a list in list assignment. Yes, of course it does, but it is just a convenient way to set up some test data and doesn't having any bearing on the use of the iterator?
Examine what is said, not who speaks.
The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead. |