This venerable variable demands more respect than many monks give it. Its might and glory are rarely actualized and this is a detriment to the perl community.
Observe this variables willingness to be noticed.
$[++; # No go.
$[+=1; # Not happening
$[ = $[; # Works.
$[ = $[ + 1; # That will work!
print \$[; # Ok, works.
$[ = \$[; # which also works
print $[; # Whoo fun!
Take notice to ' print \$[;' not to be confused with ' $[ = \$[; print $[;', but the fun doesn't stop here monks! $[=-1;
@_=qw/foo bar baz/;
print $_[-1]; # foo
print $_[-2]; # bar
print $_[-3]; # foo
After playing with $[; I have taken note to this dire mistake that I apparently have made habit. And, now I have decided to publish a finding to enlighten all. This idiom is wrong, and must be corrected at all cost.
#WRONG:
for(my $i=0; $i<$#foo; $i++){}
#RIGHT:
for(my $i=$[; $i<$#foo; $i++){}
However, for the same reason this idiom is also wrong:
#WRONG:
foreach(0..$#foo){}
#RIGHT:
foreach($[..$#foo){}
Now that two bad commonplace practices have been exposed, I suggest that we enable warnings to be issued for people who use the 0..$#foo. These willy-nilly coding practices are detrimental should be discouraged. I see them much more severe than addressing an element with the array sigil, at least Perl can correct for that. Evan Carroll
www.EvanCarroll.com
Re: $[ is under respected.
by duff (Parson) on Aug 03, 2005 at 05:25 UTC
|
I hope your post is in jest. If you were tchrist, it would clearly be hilarious. :-) But since I don't know you and it's hard to tell in this low-bandwidth, high-latency medium ...
You're about 10 years too late. The perl community has used $[ and found it painful, ergo it is soon to be extirpated.
BTW, you've got the first idiom wrong. It is:
for (my $i = 0; $i < @array; $i++) { ... }
| [reply] [d/l] [select] |
|
BTW, you've got the first idiom wrong. It is:
for (my $i = 0; $i < @array; $i++) { ... }
No, the correct idiom is usually
for my $elt (@array) { ... }
or, in those rare cases where you really do need
an index into the array, it becomes
for my $i (0 .. $#array) { ... }
C-style three-clause for loops have been deemed
unperlish, are deprecated, and have been
removed from the core language in Perl6.
If you really need the ability to manipulate
the loop variable from within the loop,
beyond what next and last provide, then
use a while loop, but in general it's
best to avoid that if possible. (Avoid
using while loops in that way, I mean,
not avoid using them at all.)
| [reply] [d/l] [select] |
|
loop my $i = 0; $i < $n; $i++ { ... }
See S04
And the C-style for loop has hardly been deemed "unperlish". If anything, it's unperlish for this particular purpose (iterating over an array index). It's certainly useful in other situations (though, in perl6, many of those situations are satisfied by other, newer language features)
| [reply] [d/l] |
Re: $[ is under respected.
by tlm (Prior) on Aug 03, 2005 at 12:30 UTC
|
I have a hard time coming up for good reasons ever to change $[ from its default.
The only situation I can imagine, and it's a very farfetched one, is if I am translating from a non-zero-based indexing language (like Fortran) into Perl some extremely complex algorithm that I barely understand and that has lots of array index manipulations. In such a rare situation, for the sake of avoiding translation mistakes I may set $[ to 1. But even this would be temporary; ultimately, with a sufficiently solid test suite to back me up, I'd refactor the whole thing to 0-based indexing.
I'd be curious to know if any other monk has found any other use for a non-zero $[.
| [reply] |
|
for my $x (0 .. $X - 1) {
for my $y (0 .. $Y - 1) {
# Do something with $array[$x][$y]
printf "bla, bla (%d, %d)", $x + 1, $y + 1;
}
}
So I may write:
{ local $[ = 1;
for my $x (1 .. $X) {
for my $y (1 .. $Y) {
# Do something with $array[$x][$y]
print "bla, bla ($x, $y)";
}
}
}
| [reply] [d/l] [select] |
|
I was recently attempting to implement an algorithm for continued fractions, in which the subscript of the variables was negative. It occurred to me that it might be convenient to fudge the index to make the implementation easier for me.
(Un)fortunately, I didn't know about $[, so I was compelled to actually understand the algorithm and write code so that Perl would be happy.
I think this is something like the Perl philosophy, not constraining people to follow a particular path. It's nice to know I *could* move the index, if I wanted to - even though I understand that if I ever did that, I'd likely be sorry...
| [reply] |
A reply falls below the community's threshold of quality. You may see it by logging in.
|
Re: $[ is under respected.
by itub (Priest) on Aug 03, 2005 at 02:57 UTC
|
I personally never use $#foo; I prefer scalar @foo. For example,
for (1 .. @foo) {}
| [reply] [d/l] |
|
| [reply] |
|
Yes ... but don't do that. Having $[ set to anything other than 0 is just asking for a world of trouble. Most modules won't cooperate, for starters. Having a global variable define the lower-bound of your arrays is going to give you issues. The right way to do this in any script of reasonable length (e.g., uses any other modules) is to be able to specify on a variable-by-variable basis what the minimum (and, optionally, maximum) index(es) is(are). Which is how any other language of note does it, if they do it at all.
Perhaps perl6 will have that. But perl5 doesn't, so don't do that.
| [reply] |
|
A reply falls below the community's threshold of quality. You may see it by logging in.
| A reply falls below the community's threshold of quality. You may see it by logging in.
|
|
Not really, for (1 .. @foo) will always loop once per array element. Where did I say that I intended to use $_ as an index to get at the elements of @foo? ;-)
| [reply] [d/l] |
Re: $[ is under respected.
by Anonymous Monk on Aug 03, 2005 at 09:05 UTC
|
Does anyone understand this:
my @foo = qw /foo bar baz quux/;
$[ = 2;
print $foo[2], "\n";
print $foo[1], "\n";
print $foo[0], "\n";
__END__
foo
quux
foo
If $[ is set to 2, $foo[2] is the first element (foo). It seems that $foo[1] is the last element (quux), which is logical because 1 == $[ - 1. But while 0 == $[ - 2, $foo[0] isn't equal to penultimate element (baz), but it's equal to the first element (foo) - as if $[ doesn't effect an index equal to 0. | [reply] [d/l] [select] |
|
|