The following is intended as a draft of the final draft of RFC 120
"Implicit counter in for statements, possibly $#".
It includes summarised alternatives based on discussions in this list. It
is not intended that this post should revive these discussions. It is a
chance for the contributing parties to confirm that their suggestions have
been fairly represented.
Look out for RFC 1357: "Refract: A meta RFC language". Anyone who cares to
debate the usefulness of a RFC definition language within Perl can meet me
in the ICA bar at YAPC::Europe.
John McNamara.
=head1 TITLE
Implicit counter in for statements, possibly $#.
=head1 VERSION
Maintainer: John McNamara <[EMAIL PROTECTED]>
Date: 15 Aug 2000
Version: 3
Mailing List: perl6-language-flow
Number: 120
Status: Frozen
=head1 ABSTRACT
The syntax of the Perl style C<for> statement could be augmented by the
introduction of an implicit counter variable. The deprecated variable C<$#>
could be used for this purpose due to its mnemonic association with C<$#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.
=head1 DESCRIPTION
The use of C<for> and C<foreach> statements in conjunction with the range
operator, C<..>, 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 C<for> statements would
lead to a more elegant syntax. It is proposed the deprecated variable C<$#>
should be used for this purpose due to its mnemonic association with
C<$#array>. For example:
foreach $item (@array) {
print $item, " is at index ", $#, "\n";
}
=head1 ALTERNATIVE METHODS
Following discussion of this proposal on perl6-language-flow the following
suggestions were made:
=head2 Alternative 1 : Explicit counter returned by a function
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";
}
=head2 Alternative 2 : Explicit counter defined after foreach
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
C<each()>:
foreach (($item, $index) = each(@array)) {
print $item, " is at index ", $index, "\n";
}
With this in mind Johan Vromans suggested the use of C<keys()> and
C<values()> on arrays.
A variation on this is an explicit counter after C<@array>. This was
alluded to by Jonathan Scott Duff:
foreach $item (@array) $index {
print $item, " is at index ", $index, "\n";
}
=head2 Alternative 3 : Explicit counter defined by a scoping statement
This was proposed by Nathan Torkington.
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";
}
=head1 IMPLEMENTATION
As Ilya says, straightforward.
=head1 REFERENCES
perlvar
Alex Rhomberg proposed an implicit counter variable on clpm:
http://x53.deja.com/getdoc.xp?AN=557218804&fmt=text and
http://x52.deja.com/threadmsg_ct.xp?AN=580369190.1&fmt=text
Craig Berry suggested C<$#>:
http://x52.deja.com/threadmsg_ct.xp?AN=580403316.1&fmt=text