Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks.

#!/usr/bin/perl use strict; use warnings; use v5.26; my %hash = (); $hash{name} = 'Michelle'; $hash{age} = 22; $hash{city} = 'Austin'; say "@{[%hash]}";


I am quite confused by the last line since it appears to be dereferencing an array. If someone could assist me in "dismantling" its syntax into a more comprehensive form, I would appreciate it. Thanks.

Michelle

Replies are listed 'Best First'.
Re: Print the contents of a hash without looping.
by LanX (Saint) on Dec 01, 2017 at 20:51 UTC
    Hi

    > say "@{[%hash]}";

    > since it appears to be dereferencing an array.

    That's because the [...] creates an anonymous array ref and the %hash is expanded to a list inside.

    I'd say this is cargo cult, say "%hash"; should have the exact same effect.

    edit

    I was wrong, it helps adding white-space through $"

    #!/usr/bin/perl use strict; use warnings; use feature 'say'; my %hash = (); $hash{name} = 'Michelle'; $hash{age} = 22; $hash{city} = 'Austin'; say "1: @{[%hash]}"; say "2: %hash"; say "3: ",%hash; say "4: ", join $",%hash;
    1: city Austin name Michelle age 22 2: %hash 3: cityAustinnameMichelleage22 4: city Austin name Michelle age 22

    but I'd certainly prefer Data::Dumper or Data::Dump here, or at least say join " ", %hash

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

      Just for completenes -

      say "%hash"; should have the exact same effect.

      Arguably it should, but it doesn't. A hash (or a construct with sigil %) is never interpolated in double quoted strings or qq(). I guess it is because, at list expansion of a hash, the sequence of key/value tuples is random. And then, the char % is meaningful for sprintf. However, hash slices are interpolated (their sigil is @). So,

      my $hash = \%hash; say "5: %$hash"; say "6: @hash{keys %hash}"; say "7: @$hash{keys $hash}";
      5: %HASH(0x1185900) 6: Michelle Austin 22 7: Michelle Austin 22
      perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      Since you bring up the subject of special variables, we should point out that your case 3 is essentially the same as case 1, but uses $, instead of $".
      do{ local $, = $"; say "5:", %hash;}
      Bill
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Print the contents of a hash without looping.
by 1nickt (Canon) on Dec 01, 2017 at 21:12 UTC

    Hi Michelle, welcome.

    it appears to be dereferencing an array ...

    Just for accurate terminology, you can't dereference an array: you dereference a scalar reference pointing to an array, thereby yielding the array.

    LanX has explained why the syntax you have "prints the contents of the hash without looping." But if that's your goal, you might like Data::Dumper. (edit: which he mentioned in his update). This built-in module is used to "dump" the contents of data structures, sometimes into permanent storage, but most often just to see what's in the hash.

    use strict; use warnings; use feature 'say'; use Data::Dumper; my %hash = ( foo => 'bar', baz => 'qux', ); say 'Hash: ' . Dumper %hash; ## Output: # Hash: $VAR1 = 'foo'; # $VAR2 = 'bar'; # $VAR3 = 'baz'; # $VAR4 = 'qux'; say 'As hashref: ' . Dumper \%hash; ## Output: # As hashref: $VAR1 = { # 'foo' => 'bar', # 'baz' => 'qux' # };
    Then there are various short ways to write a loop, if less typing is your goal (and a worthy goal it is). Here's a simple one, a "postfix for loop":
    say "$_ : $hash{ $_ }" for keys %hash;

    Hope this helps!


    The way forward always starts with a minimal test.
Re: Print the contents of a hash without looping.
by poj (Abbot) on Dec 01, 2017 at 20:57 UTC
Re: Print the contents of a hash without looping. (template)
by LanX (Saint) on Dec 02, 2017 at 20:16 UTC
    Hi again

    One information which I forgot to add is that @{[...]} is a construct to tunnel Perl code into string interpolation.

    This is handy if you don't have a template engine.

    For instance

    my $tmpl = << "__HTML__"; ... some HTML ... <h1>@{[ text ( en => "title", de => "Titel", ) ]}</h1> ... more HTML ... __HTML__

    is code I actively use in a CGI where the sub text() decides which language to insert.

    The code is executed in list context, that's why %hash get expanded to a list.

    HTH!

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