mvanle has asked for the wisdom of the Perl Monks concerning the following question:
Why are the below hash values not equal ?
use feature 'say'; my $hash; $hash{key1}{key2} = 'val1'; $hash->{key1}->{key2} = 'val2'; say $hash{key1}{key2}; say $hash->{key1}->{key2}; =comment Expected: val2 val2 Actual: val1 val2 =cut
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Hash syntax
by hippo (Archbishop) on Aug 19, 2024 at 08:09 UTC | |
Short answer: because you have not used strict like you should have done. Long answer: One is a hash and the other is a hash reference. They are two different variables, the fact that your code has chosen to give them the same name is irrelevant (and obviously confusing), so don't do that unless you have a very good reason for doing so. 🦛 | [reply] |
|
Re: Hash syntax
by Discipulus (Canon) on Aug 19, 2024 at 08:03 UTC | |
> Why are the below hash values not equal ? because you missed to
L*
There are no rules, there are no thumbs.. Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS. | [reply] [d/l] |
|
Re: Hash syntax
by LanX (Saint) on Aug 19, 2024 at 11:06 UTC | |
welcome to the monastery, :) That's because Perl has two forms for each variable type, and you are implicitly using both for hashes:
Using strict would have warned you that you didn't declare two different variables %hash and $hash beforehand. See perlreftut * Background for this "dualism" is that references were only introduced with Perl5 and the old Perl4 syntax was kept compatible. Furthermore does Perl need context, the $ upfront denotes scalar context.*
EditDemo in the debugger
Cheers Rolf
*) updated | [reply] [d/l] [select] |
by perlboy_emeritus (Scribe) on Aug 25, 2024 at 23:06 UTC | |
Hello Monks, The several answers are spot-on, including encouraging the writer to use the debugger, but I have a curious issue that is somewhat related, to wit: for my amusement I've written three great circle calculators (Spherical Law of Cosines, Haversine and Vincenty Inverse; C, Perl and Python versions) that stores airport locations and their geodesic parameters (latitude and longitude) in a Btree BerkeleyDB. The hash instances are tied with MLDBM. I load them into the DB from a tab-delimited file. Here is my airport hash definition:
$APref is a hash reference. The key is an interger rather than a location string so I can say, for example; calculate the GC distance between 17 and 33. When I access that array, as in when printing out a list or passing two airport instances to my GC calculators I would like to say: $APref->{$key}{geodesics}->[0..3]but this causes Perl (5.38.2) to barf. This expression @{$APref->{$key}{geodesics}}[0..3]is the only way to fetch that slice. My standard rule is to use the arrow operator wherever there is a reference in such an expression, but the block indirection version is the only syntax that works, in this case. Is their something about taking an array slice that defeats the arrow operator, or am I missing something? I have no problem using or understanding that noisier indirection syntax, but there must be an explanation beyond my current understanding of the arrow operator. Thoughts please? U P D A T E Thank you LanX and tybalt89. You're never too old to learn something you didn't know about Perl. ->@[0..3]is exactly what I was looking for, and context is everything; a slice is not a scalar. | [reply] [d/l] [select] |
by tybalt89 (Monsignor) on Aug 25, 2024 at 23:29 UTC | |
Close enough? | [reply] [d/l] |
by LanX (Saint) on Aug 26, 2024 at 00:54 UTC | |
> I have no problem using or understanding that noisier indirection syntax, but there must be an explanation beyond my current understanding of the arrow operator. Thoughts please?
Short answerSymmetry! $arr_ref->[@slice] doesn't "work" because the analog $arr[@slice] also doesn't do what you mean. NB: @arr[@slice] is different.
Long answerPerl is pretty consistent that $ means scalar and @ means a list. The whole context rules depend on it. Something like $ref->[@slice] is as misleading as $arr[@slice] because a scalar has to be returned. (What's happening here is that the scalar value of @slice is calculated instead of a list) For a slice the correct syntax is @arr[@slice] Compare the analogy
The deref syntax in line 16 is newer and was introduced to avoid @{...} constructs like in line 17 (In this case the brackets are optional) What you are suggesting would break the symmetry and cause confusion and bugs.
Cheers Rolf
UpdatesAdded short answer | [reply] [d/l] [select] |
|
Re: Hash syntax
by perlfan (Parson) on Aug 24, 2024 at 00:41 UTC | |
Look at the difference that dereferencing with the first -> makes: Output: To underscore the difference also, you can look at how an a HASH can be assigned with an even sized list, Output:
| [reply] [d/l] [select] |