[za-pm] 0..$#input_numbers ???

Nick Cleaton nick at cleaton.net
Tue Apr 20 21:12:42 PDT 2010


On Tue, 2010-04-20 at 23:25 +0200, Anne Wainwright wrote:

> As usual, writing a clear email about a problem has wrung most of the
> answer out of the apparent fog. Nevertheless ....
> 
> >From page 59 of INTERMEDIATE PERL (alpaca book)
> 
> 1 my @input_numbers = (1, 2, 4, 8, 16, 32, 64);
> # $len = @input_numbers;
> 2 my @indices_of_odd_digit_sums = grep {
> 3    my $number = $input_numbers[$_];
> 4    my $sum;
> 5    $sum += $_ for split //, $number;
> 6    $sum % 2;
> 
> 7 } 0..$#input_numbers;  # OR 0..$len;

Not quite - $#input_numbers is the index of the last element in
@input_numbers, whereas $len is the number of elements in
@input_numbers.  Since arrays are indexed starting from 0,
$#input_numbers is one less than $len.

> 
> 8 print "\n\t the input nos. @input_numbers";
> 9 print "\n\t the index nos. @indices_of_odd_digit_sums of the
>   odd_digit_sums\n\n";
> 
> 
> >From line 7, just where does the syntax of $#input_numbers come from?
> <Notes, not $#$input_numbers  as I might have expected in my innocence>

You don't have a $input_numbers variable there, you have an
@input_numbers array.

The way $#array works is that you replace the @ at the start of the
array name with $# to get the index of the last element.

> The only ref to $# that I find is a deprecated alternative to printf
> listed in LEARNING PERL (2nd edn. p.134). This evaluates to the same
> as my $len but must be the only place in perl where # is anything
> other than a comment marker.

The deprecated $# variable has nothing to do with the $#array syntax.
$#array is not deprecated, it's the right thing to use here.

> I can uncomment the line after line 1 and replace the syntax as
> commented on line 7, which would be my way and it works fine
> 
> 0..$input_numbers also works but, as you would know, generates minor
> warnings.

0..$input_numbers isn't doing what you think - there is no
$input_numbers anywhere else in your example.  $input_numbers will
evaluate to 0 (with a warning) because it's an uninitialised variable,
and you'll run the inner code just once rather than once for each array
element.

This is one of the reasons to get into the habit of starting your
scripts with

use strict;
use warnings;

... as these make it harder to write a script that seems to work but
isn't really doing what you think it's doing.


Nick



More information about the Za-pm mailing list