http://www.perlmonks.org?node_id=563987

tamaguchi has asked for the wisdom of the Perl Monks concerning the following question:

#!/usr/bin/perl -w I have noticed the folling: instead of using (scalar(@arr)) to indicate the number of ellements in an array it is possble to use $#arr. It seems that $# is a value 1 less then the scalar value.
@arr=('A', 'B', 'C', 'D', 'E', 'F', 'G');
instead of writing:
for(my $i=0; $i<(scalar(@arr)); $i++) {print"$i $arr[$i]\n";}
..one could make things little easier by writing:
for(my $i=0; $i<=$#arr; $i++) {print"$i $arr[$i]\n\n";}
What is this $# variable really, and is it correct to use it as shown above. I mean could it cause any problems if one uses $#x instead of scalar(x)? What is this

Replies are listed 'Best First'.
Re: $# -variable?
by GrandFather (Saint) on Jul 27, 2006 at 09:04 UTC

    $#array is the index of the last element of @array. Yes, you can use it as one end of the range of indexes as shown. However, that is hardly ever the Perl way. Generally if you want to run through the elements in an array you would:

    for my $element (@array) { print "$element\n\n"; } # or using the default variable for (@array) { print "$_\n\n"; } # or using for as a statement modifier print "$element\n\n" for @array;

    If you really need to index through the array then the Perlish way is to use a range (but see Flipin good, or a total flop?):

    for (0..$#array) { print "$array[$_]\n\n" }

    DWIM is Perl's answer to Gödel
Re: $# -variable?
by davorg (Chancellor) on Jul 27, 2006 at 09:05 UTC

    From perldata:

    The length of an array is a scalar value. You may find the length of array @days by evaluating $#days , as in csh. However, this isn't the length of the array; it's the subscript of the last element, which is a different value since there is ordinarily a 0th element. Assigning to $#days actually changes the length of the array. Shortening an array this way destroys intervening values. Lengthening an array that was previously shortened does not recover values that were in those elements.

    So $#array is the last index in @array. As arrays are indexed from zero, this will obviously one less that the result you'll get by evaluating @array in a scalar context.

    Perl has both ways to get information about the size of an array as both methods can be useful. In particular, $#array can be assigned to; which extends or truncates the array.

    Two more things to note:

    • There is also a variable called $#. It's never used. You can read about it (and why you shouldn't use it) in perlvar
    • There is another variable called $[ which controls the value that Perl uses for the first index in an array. Changing this will also change $#array. Changing the value of this variable is a very bad idea.
    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: $# -variable?
by gellyfish (Monsignor) on Jul 27, 2006 at 09:10 UTC

    $#ary is the index of the last element in the array, whilst it is highly discouraged the base of the array (i.e. the index of the first element) can be altered by setting the variable $[, so to reliably know the number of elements in an array you want to use scalar @ary.

    If you really do insist on using this to index an array then you probably want (in a C style for statement):

    for (my $i = $[; $i <= $#ary; $i++) { # ... }
    or using the more perlish idiom:
    foreach my $i ( $[ .. $#ary ) { # ... }
    Of course unless one has a pressing need to know the index one would eschew the index counter and iterate over the array directly:
    foreach my $element (@ary) { # ... }

    /J\

Re: $# -variable?
by planetscape (Chancellor) on Jul 27, 2006 at 10:27 UTC
Re: $# -variable?
by ikegami (Patriarch) on Jul 27, 2006 at 15:52 UTC

    You don't need to use the word scalar in places where it is already in a scalar context. The following are all equivalent:

    for (my $i=0; $i<scalar(@arr); $i++) for (my $i=0; $i<@arr; $i++) for (my $i=0; $i<=$#arr; $i++) for my $i (0..$#arr)

    The last one, of course, is the easiest to read by far. Unless you don't need the actual index. In that case, a foreach loop can be used.

    foreach my $item (@arr)

    The difference between the last two is that loops of the form for (expr0..expr1) are very efficient. They are implemented as counting loops, which means the list isn't flattened in memory. foreach (@array), on the other hand, makes a copy of the array before the loop starts.

A reply falls below the community's threshold of quality. You may see it by logging in.