Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Use of $# to get array size in Perl 5.10

Status
Not open for further replies.

lit8rtot

Programmer
Jul 31, 2009
5
US
I apologize if this is a repeat.

The following code works on Perl v5.8.8, but does not on v5.10.0.

#!/usr/bin/perl
use strict;

sub getListIdx {
my $listref = shift;
my $sval = shift;

for (my $i=0; $i<=$#{@{$listref}}; $i++) {
if ($sval eq $listref->[$i]) {
return $i;
}
}
return -1;
}

my @tarray = (3, 5, 6);
for my $i (1,2,3,2,4,5) {
print "i=$i\n";
if (getListIdx(\@tarray, $i) == -1) {
print "Adding unique $i\n";
push @tarray, $i;
} else {
print "Found $i again.\n";
}
}

When run on v5.10.0, I get the following:

Can't use string ("3") as an ARRAY ref while "strict refs" in use at ./x2 line 8.

I presume this has something to do with using the $# syntax to get the length of the array? Is there a better/new way of doing this that works in both versions of Perl?
 
It looks like a difference in how Perl handles the array between 5.8 and 5.10.

Here's modified code that executes on 5.10:

Code:
#!/usr/bin/perl
use strict;

sub getListIdx {
        my $listref = shift;
        my $sval = shift;

        print "sval=$sval; listref=$listref; @{$listref}\n";
        my @deref = @{$listref};
        for (my $i=0; $i<= $#deref; $i++) {
                if ($sval eq $listref->[$i]) {
                        return $i;
                }
        }
        return -1;
}

my @tarray = (3, 5, 6);
for my $i (1,2,3,2,4,5) {
        print "i=$i\n";
        if (getListIdx(\@tarray, $i) == -1) {
                print "Adding unique $i\n";
                push @tarray, $i;
        } else {
                print "Found $i again.\n";
        }
}

It looks like what Perl 5.10 was doing in your code was:

Code:
for (my $i=0; $i<=$#{[blue]@{$listref}[/blue]}; $i++) {
for (my $i=0; $i<=$#{[blue]3 5 6[/blue]}; $i++) {
for (my $i=0; $i<=[red]$#{[/red][blue]3 5 6[/blue]}; $i++) {

Can't use a string ("3") as an ARRAY ref while "strict refs" in use

It looks like it expands @{$listref} before handling the $# syntax.

I always just use scalar() to get the length of an array.

Cuvou.com | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
Here's the proper way of doing what you were doing:

Code:
#!/usr/bin/perl
use strict;

sub getListIdx {
        my $listref = shift;
        my $sval = shift;

        for (my $i=0; $i<= [blue]$#{$listref}[/blue]; $i++) {
                if ($sval eq $listref->[$i]) {
                        return $i;
                }
        }
        return -1;
}

my @tarray = (3, 5, 6);
for my $i (1,2,3,2,4,5) {
        print "i=$i\n";
        if (getListIdx(\@tarray, $i) == -1) {
                print "Adding unique $i\n";
                push @tarray, $i;
        } else {
                print "Found $i again.\n";
        }
}

That Perl 5.8 worked on your code looks like it was a bug, actually; the $# characters are a replacement to the @ character in this case iirc, so there should be no @ involved in there at all.

Cuvou.com | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
This is definetly wrong:

$#{@{$listref}}


that's a double-layering of dereferencing and should have been:

$#{$listref}

I don't know why it would work in 5.8 with "strict" turned on.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top