Reputation: 161
Fragment A below works, copying an array by dereferencing an array ref.
Fragment B, deeper in some real code, does not. The commented-out line is not part of the real code, which works fine (%ips is a hash in which each key is an IP address and each value is a reference to an array).
But why does the commented-out line fail with the message
Global symbol "$ips" requires explicit package name at ...
my $a1 = [1,2,3];
say $$a1[1];
my @a2 = @$a1;
say "@a2";
else {
# Initialise count to 1,
# set both dates:
$ips{$1} = [1, $2, $2];
# my @arr = @$ips{$1}; # error...
}
Upvotes: 1
Views: 148
Reputation: 386676
@$ips{$1}
is short for
@{ $ips }{$1} # Hash slice, like @hash{"a", "b", "c"}
but you want
@{ $ips{$1} } # Array, like @array
Scalar Direct $NAME $scalar
Scalar By ref (simple) $$NAME $$scalar_ref
Scalar By ref $BLOCK ${ $scalar_ref }
Array Direct @NAME @array
Array By ref (simple) @$NAME @$array_ref
Array By ref @BLOCK @{ $array_ref }
Hash Direct %NAME %hash
Hash By ref (simple) %$NAME %$hash_ref
Hash By ref %BLOCK %{ $hash_ref }
Hash element Direct $NAME{EXPR} $hash{key}
Hash element By ref (simple) $$NAME{EXPR} $$hash_ref{key}
Hash element By ref $BLOCK{EXPR} ${ $hash_ref }{key}
Hash slice Direct @NAME{LIST} @hash{qw( a b c )}
Hash slice By ref (simple) @$NAME{LIST} @$hash_ref{qw( a b c )}
Hash slice By ref @BLOCK{LIST} @{ $hash_ref }{qw( a b c )}
Array element Direct $NAME[EXPR] $array[3]
Array element By ref (simple) $$NAME[EXPR] $$array_ref[3]
Array element By ref $BLOCK[EXPR] ${ $array_ref }[3]
Array slice Direct @NAME[LIST] @array[3..5]
Array slice By ref (simple) @$NAME[LIST] @$array_ref[3..5]
Array slice By ref @BLOCK[LIST] @{ $array_ref }[3..5]
Upvotes: 2
Reputation: 1901
The problem with using code like:
@$ips{$1}
is that you think that "@" is dereferencing "$ips{$1}" (so it can be assigned to an array), but in reality that line is using "{$1}" to get an element from "@$ips".
The "@" and "$" sigils bind more tightly than "{$1}" does, so the above is closer to:
(@$ips) {$1}
than what you want, which is:
@ ($ips{$1})
To overcome this, you can tell Perl to have the "@" sigil work on "$ips{$1}" by putting "$ips{$1}" in curly brackets, like this:
@{$ips{$1}}
This way, there's no ambiguity over which happens first.
Upvotes: 2
Reputation: 50677
Perl is looking for $ips
variable as you've made mistake when dereferencing %ips
hash. You can
my @arr = @{ $ips{$1} };
or
my $ref = $ips{$1};
my @arr = @$ref; # or @{ $ref }
Upvotes: 3