Reputation: 31
Straight from https://perldoc.perl.org/perlref.html
I don't understand below
$$hashref{"KEY"} = "VALUE"; # CASE 0
${$hashref}{"KEY"} = "VALUE"; # CASE 1
${$hashref{"KEY"}} = "VALUE"; # CASE 2
${$hashref->{"KEY"}} = "VALUE"; # CASE 3
What is the difference between case 1 and 2?
I am thinking anything inside ${}
is a pointer to some address so it's like
my $hashref = \%hash;
${$hashref}{"KEY"}
is really $$hashref{"KEY"}
and this is dereferencing \%hash
and looking up it's "KEY"
${$hashref->{"KEY"}}
.. I would think is.. ?? I thought the rule was the bind closest to the left so I thought this also became $$hashref->{"KEY"}
. which is same as ${$hashref}{'KEY'}
. Am I getting this wrong?
Upvotes: 3
Views: 92
Reputation: 66873
The difference between cases 0 and 1 is that in case 1 a block of code may be used inside ${}
, which returns a hashref. Some things work without a {}
, like the specific example in case 1, but some can't. It says elsewhere in perlref
Anywhere you'd put an identifier (or chain of identifiers) as part of a variable or subroutine name, you can replace the identifier with a simple scalar variable containing a reference of the correct type
...
Anything more complicated than a simple scalar variable must use methods 2 or 3 below.
...
Anywhere you'd put an identifier (or chain of identifiers) as part of a variable or subroutine name, you can replace the identifier with a BLOCK returning a reference of the correct type.
(emphasis mine)
An example
sub get_hr { return { a => 1, b => 2 } }
say ${ get_hr() }{a}
may go a bit overboard (and is unfit for production) but hopefully conveys it.
A lot of other clarifications are provided in the answers by amon and by ikegami.
Also see Using references in perlreftut and Caveats on precedence in perldsc
Upvotes: 0
Reputation: 385496
$NAME
(e.g. $foo
) is a scalar variable.$BLOCK
(e.g. ${ $ref }
) is a scalar variable (via a reference).$$NAME
(e.g. $$ref
) is short for ${ $NAME }
(e.g. ${ $ref }
).Similarly,
$NAME{EXPR}
(e.g. $foo{bar}
) is a hash element.$BLOCK{EXPR}
(e.g. ${ $ref }{bar}
) is a hash element (via a reference).$$NAME{EXPR}
(e.g. $$ref{bar}
) is short for ${ $NAME }{EXPR}
(e.g. ${ $ref }{bar}
).So,
$$hash_ref{"KEY"}
is short for ${ $hashref }{"KEY"}
${ $hash_ref }{"KEY"}
is a hash element.$hashref
is a reference to the hash.${ $hash{"KEY"} }
is a scalar variable.$hash{"KEY"}
is a reference to the scalar.%hash
is a hash.${ $hash_ref->{"KEY"} }
is a scalar variable.$hash_ref->{"KEY"}
is a nice way to write $$hash_ref{"KEY"}
.)$hash_ref->{"KEY"}
is a reference to the scalar.$hash_ref
is a reference to a hash.Upvotes: 0
Reputation: 57590
Case 0 and 1 are equivalent, these you have understood correctly.
Case 2 is a bit subtle:
${$hashref{"KEY"}} = "VALUE";
First, this executes $hashref{"KEY"}
which looks up the "KEY"
in a hash variable called %hashref
. Despite its name it is a hash, not a hash reference! This returns a value in that hash.
Next, we dereference that value in the hash as a scalar reference: ${ ... }
.
Finally, we assign a "VALUE"
to the scalar reference target.
Case 3 is similar, but actually uses a hash reference.
If we rewrite Case 2 and 3, their relation might be clearer:
{ # Case 2
my %hash;
${ $hash{"KEY"} } = "VALUE";
}
{ # Case 3
my %hash;
my $hashref = \%hash;
${ $hashref->{"KEY"} } = "VALUE";
}
Additional remarks:
The ${ … }
dereference operator does not bind closest to left, it contains the value that will be dereferenced. The $$foo
form is a short form of the ${ … }
dereference operator if the reference is a normal scalar variable, as opposed to a more complex expression. This is not only the case for scalar references but also array refs (@{ … }
and @$foo
) and hash refs (%{ … }
and %$foo
).
The sigil ($ % @) of a dereference operator is not the type of the reference, but depends on whether we are accessing one or more values in the reference target.
When we access a single value in a hash %hash
this looks like $hash{"KEY"}
.
When we access a single value in a $hashref
, this looks like $hashref->{"KEY"}
or ${$hashref}{"KEY"}
or $$hashref{"KEY"}
.
Despite the $
there is no scalar reference here. The scalar dereference operator ${ … }
is essentially a separate operator from the hash reference subscript operator ${ … }{ … }
.
The expression $$foo->{"KEY"}
features a scalar reference to a hash reference! Firs the scalar reference $foo
is dereferenced $$foo
to a hash ref, in which a value …->{"KEY"}
is accessed.
Upvotes: 1