How can #? be used on a dereferenced array without first using @?

  • A+

An array in perl is dereferenced like so,

my @array = @{$array_reference}; 

When trying to assign an array to a dereference without the '@', like,

my @array = {$array_reference}; 

Perl throws the error, 'Odd number of elements in anonymous hash at ./ line 22.' We can't assign it to an array variable becauase Perl is confused about the type.

So how can we perform...

my $lastindex = $#{$array_reference}; 

if Perl struggles to understand that '{$array_reference}' is an array type? It would make more sense to me if this looked like,

my $lastindex = $#@{$array_reference}; 

(despite looking much uglier).


tl;dr: It's $#{$array_reference} to match the syntax of $#array.

{} is overloaded with many meanings and that's just how Perl is.

Sometimes {} creates an anonymous hash. That's what {$array_reference} is doing, trying to make a hash where the key is the stringification of $array_reference, something like "ARRAY(0x7fb21e803280)" and there is no value. Because you're trying to create a hash with a key and no value you get an "odd number of elements" warning.

Sometimes {...} is a block like sub { ... } or if(...) { ... }, or do {...} and so on.

Sometimes it's a bare block like { local $/; ... }.

Sometimes it's indicating the key of a hash like $hash{key} or $hash->{key}.

Preceeded with certain sigils {} makes dereferencing explicit. While you can write $#$array_reference or @$array_reference sometimes you want to dereference something that isn't a simple scalar. For example, if you had a function that returned an array reference you could get its size in one line with $#{ get_array_reference() }. It's $#{$array_reference} to match the syntax of $#array.

$#{...} dereferences an array and gets the index. @{...} dereferences an array. %{...} dereferences a hash. ${...} dereferences a scalar. *{...} dereferences a glob.

You might find the section on Variable Names and Sigils in Modern Perl helpful to see the pattern better.

It would make more sense to me if this looked like...

There's a lot of things like that. Perl has been around since 1987. A lot of these design decisions were made decades ago. The code for deciding what {} means is particularly complex. That there is a distinction between an array and an array reference at all is a bit odd.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: