Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

  (email not shown publicly)
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Friday July 14, 2006
09:54 AM

How not to count the elements in an array

[ #30285 ]

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<foo bar baz>; 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)";

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.
  • This one (mis-)feature of Perl is one of my least favorite.

    The problem is that $[ 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.

    The issue here is that the idiom for counting elements in an array should be $count = @array. However, the $count = $#array + 1 idiom (mostly) works, and meets another criteria Perl aims to f
  • ... looping through the index for all elements in an array using
    for my $i (0 .. $#array) {
    Again, the code is written under the assumption that the first array element has index 0.
    • Eeek, so our loops that require indexes should look like this? for my $i ($[ .. $#array) { ... } Wow, I have a lot of almost working code :)
      • Worse yet, you should almost never use that index. Try to do

        foreach my $elem (@array)
        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.
        J. David works really hard, has a passion for writing good software, and knows many of the world's best Perl programmers
    • 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.

  • I'll lose one of my major "I really need to look at this code closely" flags :-)