Perl referencing hash dereferencing
Consider the following simple code snippet:
%hash = ('a'=>1,'b'=>2); print $hash{'b'}; print "\n",(\%hash)->{'b'}; #used when hashes are passed by reference #to subroutines
The conclusion, as expected, is a pair of two. But I thought that $ hash {key} is a shorthand for links and dereferences executed as (\% hash) → {key}, or it is a completely different way to achieve the same result.
Please provide some clarification.
They are slightly different, because unlike many other languages, where all complex types are available only as links, Perl has an actual simple hash type and a separate reference type, which can act as a proxy server for any other type. This can be found in perlguts .
In the end, these two examples retrieve data from one storage, of course, but the second call is a bit longer because it spends time obediently, creating a link to a regular HV, and then looking for it back the way you asked. You can learn the details of what is happening under the hood using B::Concise
.
%hash = ('a'=>1,'b'=>2); print $hash{'b'}; print (\%hash)->{'b'};
Brief conclusion:
$ perl -MO=Concise deref.pl t <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 deref.pl:1) v:{ ->3 b <2> aassign[t3] vKS ->c - <1> ex-list lKP ->8 3 <0> pushmark s ->4 4 <$> const[PV "a"] s ->5 5 <$> const[IV 1] s ->6 6 <$> const[PV "b"] s ->7 7 <$> const[IV 2] s ->8 - <1> ex-list lK ->b 8 <0> pushmark s ->9 a <1> rv2hv[t2] lKRM*/1 ->b 9 <#> gv[*hash] s ->a c <;> nextstate(main 1 deref.pl:2) v:{ ->d i <@> print vK ->j d <0> pushmark s ->e h <2> helem sK/2 ->i f <1> rv2hv sKR/1 ->g e <#> gv[*hash] s ->f g <$> const[PV "b"] s ->h j <;> nextstate(main 1 deref.pl:3) v:{ ->k s <2> helem vK/2 ->t q <1> rv2hv[t7] sKR/1 ->r p <@> print sK ->q k <0> pushmark s ->l o <1> refgen lK/1 ->p - <1> ex-list lKRM ->o l <0> pushmark sRM ->m n <1> rv2hv[t6] lKRM/1 ->o m <#> gv[*hash] s ->n r <$> const[PV "b"] s ->s deref.pl syntax OK
But I thought that $ hash {key} is a shorthand for links and dereferences performed as (\% hash) → {key}, or it is a completely different route to achieve the same result.
No, $ hash {key} is just access to% hash in the same way that $ array [0] is just access to @array. But the \% hash is a reference to% hash and therefore requires dereferencing to access it. The syntax (\%hash)->{key}
would be short for:
do { my $temp_ref = \%hash; $temp_ref->{key} }
But if you have hash hash, $ hash {key} works beautifully without useless reference / dereferencing. Hashes and arrays (as a rule) are passed by reference to subprograms, since smoothing the list of pearls makes it difficult to transfer more than one. (One common exception is a function that implements named parameters.)
See perldoc perreftut
and perldoc perlref
for a full explanation of references in perl.
The sigle ($% @) changes in Perl 5 because it reflects the available value.
my @a = (10, 20, 30); # Whole array print $a[1]; # Single scalar element of @a my %h = (a=>1, b=>2); # Whole hash print $h{a}; # Single scalar value from %h
All links refer to "$" since they are all scalars. Does it help?