[% setvar title Implicit counter in for statements, possibly $#. %]
Note: these documents may be out of date. Do not use as reference! |
To see what is currently happening visit http://www.perl6.org/
Implicit counter in for statements, possibly $#.
Maintainer: John McNamara <jmcnamara@cpan.org> Date: 16 Aug 2000 Last Modified: 27 Sep 2000 Mailing List: perl6-language-flow@perl.org Number: 120 Version: 5 Status: Frozen Frozen since: v3
The syntax of the Perl style for
statement could be augmented by the
introduction of an implicit counter variable. The deprecated variable
$#
could be used for this purpose due to its mnemonic association
with $#array
.
Other alternatives are also proposed: an explicit counter returned by a function; an explicit counter defined after foreach; an explicit counter defined by a scoping statement.
The use of for
and foreach
statements in conjunction with the
range operator, ..
, are generally seen as good idiomatic Perl:
@array = qw(sun moon stars rain); foreach $item (@array) { print $item, "\n"; }
as opposed to the "endearing attachment to C" style:
for ($i = 0; $i <= $#array; $i++) { print $array[$i], "\n"; }
In particular, the foreach statement provides a useful level of abstraction when iterating over an array of objects:
foreach $object (@array) { $object->getline; $object->parseline; $object->printline; }
However, the abstraction breaks down as soon as there is a need to access the index as well as the variable:
for ($i = 0; $i <= $#array; $i++) { # Note $array[$i]->index = $i; $array[$i]->getline; $array[$i]->parseline; $array[$i]->printline; } # Note - same applies to: foreach $i (0..$#array)
Here we are dealing with array variables and indexes instead of objects.
The addition of an implicit counter variable in for
statements would
lead to a more elegant syntax. It is proposed the deprecated variable
$#
should be used for this purpose due to its mnemonic association
with $#array
. For example:
foreach $item (@array) { print $item, " is at index ", $#, "\n"; }
Following discussion of this proposal on perl6-language-flow the following suggestions were made:
This was proposed by Mike Pastore who suggested reusing pos() and by Hildo Biersma who suggested using position():
foreach $item (@array) { print $item, " is at index ", pos(@array), "\n"; } # or: foreach $item (@array) { $index = some_counter_function(); print $item, " is at index ", $index, "\n"; }
This was proposed by Chris Madsen and Tim Jenness, Jonathan Scott Duff made a similar pythonesque suggestion:
foreach $item, $index (@array) { print $item, " is at index ", $index, "\n"; }
Glenn Linderman added this could also be used for hashes:
foreach $item $key ( %hash ) { print "$item is indexed by $key\n"; }
Ariel Scolnicov suggested a variation on this through an extension of
the each()
:
while (($item, $index) = each(@array)) { print $item, " is at index ", $index, "\n"; }
With this in mind Johan Vromans suggested the use of keys()
and
values()
on arrays.
A variation on this is an explicit counter after @array
. This was
alluded to by Jonathan Scott Duff:
foreach $item (@array) $index { print $item, " is at index ", $index, "\n"; }
This was proposed by Nathan Torkington. This behaves somewhat similarly to Tie::Counter.
foreach $item (@array) { my $index : static = 0; # initialized each time foreach loop starts print "$item is at index $index\n"; $index++; } # or: foreach $item (@array) { my $index : counter = 0; # initialized to 0 first time # incremented by 1 subsequently print "$item is at index $index\n"; }
There was no discussion about how this might be implemented. It was pointed out by more than one person it would inevitably incur an overhead.
perlvar
Alex Rhomberg proposed an implicit counter variable on clpm: x53.deja.com&fmt=text and x52.deja.com&fmt=text
Craig Berry suggested $#
:
x52.deja.com&fmt=text