in reply to Hash syntax

Hi,

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.*

Edit

Demo in the debugger

~ $ perl -de0 ... DB<4> $hash{key1} = 'val1' # add scalar to %hash DB<5> say %hash # list form key1val1 DB<6> x \%hash # dump 0 HASH(0xb400007063b64e70) 'key1' => 'val1' DB<7> use strict; $hash{key1} = 'val1' Variable "%hash" is not imported at... # versa DB<8> $hash->{key2} = 'val2' # add scalar to $hash DB<9> say $hash # hash ref HASH(0xb400007063ceb198) DB<10> x $hash # dump 0 HASH(0xb400007063ceb198) 'key2' => 'val2' DB<11> use strict; $hash->{key2} = 'val2' Variable "$hash" is not imported at

Cheers Rolf
(addicted to the Perl Programming Language :)
see Wikisyntax for the Monastery

*) updated

Replies are listed 'Best First'.
Re^2: Hash syntax
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->{++$id} = { APname => $loc, geodesics => [ $lat, $long, dms2rad($lat), dms2rad($long) ] };

    $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.

      $APref->{$key}{geodesics}->@[0..3]

      Close enough?

      This should be a proper thread, I considered that it's moved into one.

      > 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 answer

      Symmetry!

      $arr_ref->[@slice] doesn't "work" because the analog $arr[@slice] also doesn't do what you mean.

      NB: @arr[@slice] is different.

      Long answer

      Perl 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

      DB<12> @a = "a".."z"; $ar = \@a DB<13> p $ar->[1], $a[1] bb DB<14> @slice = 1..3 DB<15> p $ar->[@slice], $a[@slice] dd DB<16> p $ar->@[@slice], @a[@slice] bcdbcd DB<17> p @$ar[@slice], @a[@slice] bcdbcd

      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
      (addicted to the Perl Programming Language :)
      see Wikisyntax for the Monastery

      Updates

      Added short answer