Due to a question asked at work, I remembered that I see a lot of Perl books (PERL books, actually), recommend the following as a way of counting the elements in an array:
my $count = $#array + 1;
On the off chance you do this, it's wrong. $count is now assigned a value one greater than the last index value, not the number of elements in the array. Almost every single time you do this, you're probably going to get the answer you expect, but because you're using something for a purpose other than what it was intended for, you should not be surprised when it doesn't always do what you want.
$ perl -le '$[ = 4; my @a = qw; print $#a + 1'
Sure, you could argue that you will never alter the contents of $[, so you're therefore safe. The problem is, you know that sometimes that can give the wrong answer. Why use something you know won't always work? I don't get it. Just use context. It's both correct and easier to read.
my $count = @array; # or, if you must be explict: print "We have ", scalar @orders, " order(s)";
$[
was added for one specific purpose: to vary the base index between 0 and 1 as an aid to Fortran programmers who had trouble adjusting to the world of zero based indexing. Most people don't realize that $[
exists, or why it exists, sadly.$count = @array
. However, the $count = $#array + 1
idiom (mostly) works, and meets another criteria Perl aims to fufill: it should be comfortable to use regardless of your background. If you're a dyed in the wool C programmer, you should feel free to use a C-like pidgin of Perl and C (including $c = $#a + 1
). However, you should be encouraged, but not required to adopt Perlish idioms at your own pace (including $c = @a
).$[
exists, it could be set to some nonsensical value like 3
or -4
. That's possible, but quite improbable. Using an argument about something improbable to convince someone to stop using a C-like idiom and start using a native Perl idiom is, well, unconvincing.$c = $#a + 1
, please find a better, less improbable argument, or just accept that it exists for a reason (albeit a dubious one).
Re:Perly Warts
sigzero on 2006-07-14T16:31:46
If it (mostly) works then you should tell them how it always works. No?
Again, the code is written under the assumption that the first array element has index 0.for my $i (0.. $#array) {
...
}
Re:It's not any worse than...
jmcada on 2006-07-14T18:25:30
Eeek, so our loops that require indexes should look like this?
for my $i ($[.. $#array) { ... }
Wow, I have a lot of almost working code:) Re:It's not any worse than...
jdavidb on 2006-07-14T20:52:25
Worse yet, you should almost never use that index. Try to do
if at all possible. The only time I use an index is when I have two parallel arrays. Using this other idiom completely eliminates the index: you just access the things you want to get to directly.foreach my $elem (@array)Re:It's not any worse than...
Ovid on 2006-07-14T19:38:20
Ugh. My beautiful argument is lying there twitching. I'll shut up now.
Why use something you know won't always work?
Good luck with that argument. Meanwhile, my campaign to get people to call methods as methods, not functions, has stalled.
There is a small advantage of using $#array + 1 over @array: the former will give you the number of elements regardless of its context (assuming $[ isn't set). @array won't give you the number of elements when used in list context.
And I bet more people get bitten by an unexpected context, then by $[ being set to a non-zero value.