in reply to Re: Re: Starting foreach at an arbitrary position
in thread Starting foreach at an arbitrary position
Your right about the output. I originally typed the test code into a perl shell like so.
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.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Re: Re: Re: Starting foreach at an arbitrary position
by MarkM (Curate) on Jan 17, 2003 at 22:06 UTC | |
by BrowserUk (Patriarch) on Jan 17, 2003 at 23:53 UTC |