last index of array reference

R

Ryan Tate

If I have an array @array, I can get the last index with $#array.

What is the equivalent way to get the last index of array reference
$array?

I thought $#{@$array} would work, but perl coughed up "Bizarre copy of
ARRAY in leave at /script.pl line 230."

Haven't been able to find anything in this in Camel or Google Groups.

Thanks for any help

Cheers
r
 
M

Michael Budash

Ryan Tate said:
If I have an array @array, I can get the last index with $#array.

What is the equivalent way to get the last index of array reference
$array?

I thought $#{@$array} would work, but perl coughed up "Bizarre copy of
ARRAY in leave at /script.pl line 230."

works for me using perl 5.8.1
 
P

Paul van Eldijk

If I have an array @array, I can get the last index with $#array.

What is the equivalent way to get the last index of array reference
$array?

I thought $#{@$array} would work, but perl coughed up "Bizarre copy of
ARRAY in leave at /script.pl line 230."

Try: $#{$array}

HTH
Paul
 
L

Louis Erickson

: If I have an array @array, I can get the last index with $#array.

: What is the equivalent way to get the last index of array reference
: $array?

: I thought $#{@$array} would work, but perl coughed up "Bizarre copy of
: ARRAY in leave at /script.pl line 230."

: Haven't been able to find anything in this in Camel or Google Groups.

Hmm. I thought, "What a cool error message!" and wanted to see what
'use diagnostics' would say about it. So I wrote:

#! /usr/bin/perl

use strict;
use warnings;
my @a=qw(One Two Three);
my $r = \@a;
print "num: ", $#a, "\n";
print "num: ", $#{@$r}, "\n";

__END__

Running it gets:

$ perl foo.pl
num: 2
num: 2

That looks to be working just as you expected it to, doesn't it?

What version of Perl are you using? My 5.6.0 on Linux and 5.6.1 on Win32
both work. 5.8.2 for Cygwin also works. Those are all I have handy
at the moment.
 
A

Anno Siegel

Michael Budash said:
works for me using perl 5.8.1

It does, in 5.6.0 thru 5.9.0, but should it?

The canonical form is "$#{$arrayref}", which is derived from "$#array"
by replacing the identifier "array" with a block "{$arrayref}" which
returns a reference (symbolic or real) to an object of the right type.

Why it works with an array instead of an array reference is anybody's
guess.

Anno
 
B

Ben Morrow

Louis Erickson said:
: I thought $#{@$array} would work, but perl coughed up "Bizarre copy of
: ARRAY in leave at /script.pl line 230."

Hmm. I thought, "What a cool error message!" and wanted to see what
'use diagnostics' would say about it. So I wrote:
<snip>

perldiag says it's an internal error (otherwise known as a bug in perl
:)... rather as I suspected.

Interestingly, $#@a fails as expected, but $#{@a} succeeds...

Ben
 
A

Anno Siegel

Abigail said:
Anno Siegel ([email protected]) wrote on MMMDCCXXVI
September MCMXCIII in <URL:}} > In article <[email protected]>,
}} >
}} > > If I have an array @array, I can get the last index with $#array.
}} > >
}} > > What is the equivalent way to get the last index of array reference
}} > > $array?
}} > >
}} > > I thought $#{@$array} would work, but perl coughed up "Bizarre copy of
}} > > ARRAY in leave at /script.pl line 230."
}} >
}} > works for me using perl 5.8.1
}}
}} It does, in 5.6.0 thru 5.9.0, but should it?

It has always worked this way, AFAIK.

Apparently. I never noticed.

[...]
It seems to work with just $#{@array}. @{@array} doesn't give you a list
of elements of @array.

No, it does what it should do: evaluate @array in scalar context, i.e.
take its length, and access the corresponding regex capture variable $<n>
(if symbolic references are allowed).

Similarly, $#{ @array} "ought to" return the top index of @<n>. The
actual behavior could be meant to be a case of DWIM, though I doubt it.
It isn't documented, afaik, and it shouldn't be used except for obfuscation.

Anno
 
R

Ryan Tate

| It seems to work with just $#{@array}. @{@array} doesn't give you a list
| of elements of @array.

I tried a simple replication of the error with perl5.005 -e and
couldn't immediately reproduce, so I did some digging.

Strangely, the problem appears related to taint mode.

Here is how I was able to reproduce the problem. This was done under
perl5.005 and then the same behavior was reproduced under perl5.6 and
perl5.8.

First of all, it is not reproducable from the command line using -e
(!), as I will show below. So I created the file test_leave_error,
which contains (between the lines):

----------------
my $arrayref=['one','two','three'];
print foreach 0 .. $#{@$arrayref};
----------------

Then I tried the following from the shell. (I have inserted two
linebreaks to make the perl output, when there was some, stand out
from the shell prompt):

----------------
apocalypse.OCF.Berkeley.EDU [56] perl -wT test_leave_error
Bizarre copy of ARRAY in leave at test_leave_error line 2.
apocalypse.OCF.Berkeley.EDU [57] perl -w test_leave_error
012
apocalypse.OCF.Berkeley.EDU [58] perl -ewT '$arrayref=["one","two","three"];print foreach 0 .. $#{@$arrayref}'
apocalypse.OCF.Berkeley.EDU [59] perl -ew '$arrayref=["one","two","three"];print foreach 0 .. $#{@$arrayref}'
apocalypse.OCF.Berkeley.EDU [60] perl -e '$arrayref=["one","two","three"];print foreach 0 .. $#{@$arrayref}'
012
apocalypse.OCF.Berkeley.EDU [61]
----------------

As you can see, the shell produced no output at all until warnings
were turned off.

At this point, in my code, which must run under taint mode, I have
reverted to using ((length @$arrayref) - 1).

Cheers
R
 
R

Ryan Travis Tate

| At this point, in my code, which must run under taint mode, I have
| reverted to using ((length @$arrayref) - 1).

Erm, after re-reading the thread, I have switched to the significant
less brain dead $#{$arrayref}, which seems to work just fine, taint or
no. No point, I suppose, worrying why the other version works in some
cases but not others. IIRC & FWIW, the only reason I thought to do it
that way was I saw someone else do something like $#{1 .. 3}, which as
it turns out itself produces interesting results.
 
P

Peter Dintelmann

Hi,

Ryan Tate said:
If I have an array @array, I can get the last index with $#array.

What is the equivalent way to get the last index of array reference
$array?

perl -le '$x=[0,1,2,3]; print $#$x'
3

HTH,

Peter
 
B

Brad Baxter

| At this point, in my code, which must run under taint mode, I have
| reverted to using ((length @$arrayref) - 1).

Erm, after re-reading the thread, I have switched to the significant
less brain dead $#{$arrayref}, which seems to work just fine, taint or
no. No point, I suppose, worrying why the other version works in some
cases but not others. IIRC & FWIW, the only reason I thought to do it
that way was I saw someone else do something like $#{1 .. 3}, which as
it turns out itself produces interesting results.

Or simply $#$arrayref.

perl -le '$arrayref=[1,2,3];print $#$arrayref' prints "2"


Perhaps beside the point:

perl -le 'print $#{[1..3]}' prints "2"

perl -le 'print $#{1 .. 3}' prints "-1"

perl -le 'print $#{1}' prints "-1"

Curious.

I see in perldoc pervar:

The following are equivalent:

@whatever = ();
$#whatever = -1;

But I'm not sure I'm enlightened. :)

Regards,

Brad
 
J

Jeff 'japhy' Pinyan

Brad Baxter ([email protected]) wrote on MMMDCCXXVIII September
MCMXCIII in <URL:
:) perl -le 'print $#{1 .. 3}' prints "-1"

Ah, a combination of *two* weirdnesses. First the $#{ARRAY} that's
been the subject of the thread, and secondly that 1 .. 3 under certain
conditions returns an array:

Well, that's not what's happening. I expected this:

@1 = qw( two elements );
@2 = qw( );
@3 = qw( this has four elements );
@{"4E0"} = qw( ah ha );

print "$#{1 .. 4}: $_" while <DATA>;
__DATA__
foo
bar
blat
quux

to output:

1: foo
-1: bar
3: blat
1: quux

Because the $#{1 .. 4} is the scalar flip-flop, and it's equivalent to
$#{($. == 1) .. ($. == 4)}. The last time that's true, of course, it
returns the value of $. with "E0" appended to it.
 
B

Brad Baxter

Brad Baxter ([email protected]) wrote on MMMDCCXXVIII September
MCMXCIII in <URL::)
:) perl -le 'print $#{[1..3]}' prints "2"

Expected, [1 .. 3] is a reference to an array.
Agreed.


:) perl -le 'print $#{1 .. 3}' prints "-1"

Ah, a combination of *two* weirdnesses. First the $#{ARRAY} that's
been the subject of the thread, and secondly that 1 .. 3 under certain
conditions returns an array:

$ perl -le 'map {print ++ $_} 1, 2, 3'
Modification of a read-only value attempted at -e line 1.
$ perl -le 'map {print ++ $_} 1 .. 3'
234
$
Bizarre.


:) perl -le 'print $#{1}' prints "-1"

perl -le '@1 = (1 .. 3); print $#{1}' prints "2"

Cool.


Thanks! :)

Brad

--
#!/usr/local/bin/perl
use strict;
use warnings;

sub AUTOLOAD{ $_ = $main::AUTOLOAD;s }
..+::(.+)}$1}x;m$_$?s?_?$/?:s:.+:$_$":;
print} use subs qw;

Just another Perl _
Hacker am I few of mine _
awards are many ;;_

mine are awards few _
many of another Just _
I am Hacker Perl _
 
B

Brad Baxter

Well, that's not what's happening. I expected this:

@1 = qw( two elements );
@2 = qw( );
@3 = qw( this has four elements );
@{"4E0"} = qw( ah ha );

print "$#{1 .. 4}: $_" while <DATA>;
__DATA__
foo
bar
blat
quux

to output:

1: foo
-1: bar
3: blat
1: quux

Because the $#{1 .. 4} is the scalar flip-flop, and it's equivalent to
$#{($. == 1) .. ($. == 4)}. The last time that's true, of course, it
returns the value of $. with "E0" appended to it.

Holy cow. Yes, I get it now. No, I don't expect to go there.

Regards,

Brad
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top