http://www.perlmonks.org?node_id=969193

perl@1983 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, Can someone please help to clarify what is the difference between below three declarations (please note the brackets):
Example 1:
my %h = { ( 1 => "j", 2 => "b", ), ( 1 => "p", 2 => "b", ), };
Example 2:
my %h = ( ( 1 => "j", 2 => "b", ), ( 1 => "p", 2 => "b", ), );
Example 3:
my %h = { { 1 => "j", 2 => "b", }, { 1 => "p", 2 => "b", }, };
Thanks in advance.

Replies are listed 'Best First'.
Re: Difference in Hash Declaration
by moritz (Cardinal) on May 07, 2012 at 07:23 UTC

    Round parens don't create any substructures. Curly braces create hash references, see perlreftut.

    Putting a hash reference in a position where a hash key is expected doesn't make any sense, because it is converted to a string which loses all the interesting information that way.

Re: Difference in Hash Declaration
by tobyink (Canon) on May 07, 2012 at 07:23 UTC

    The difference is that Example 2 (using parentheses) is correct and the others are broken.

    Braces (i.e. { and }) are used (amongst other things) to create hash references. So...

    my %hash = ( foo => 1, bar => 2 ); my $hashref = { foo => 1, bar => 2 };
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: Difference in Hash Declaration
by jwkrahn (Abbot) on May 07, 2012 at 11:25 UTC

    A list can only contain scalar values, for example: ( 1, 'a', [], {}, sub{}, $scalar, \$scalar, \@array, \%hash, \&subroutine, \*type_glob ), (a number, a string, an anonymous array, an anonymous hash, an anonymous subroutine, a scalar variable, a reference to a scalar variable, a reference to an array, a reference to a hash, a reference to a subroutine, a reference to a type glob.)

    In Example 1 you are assigning an anonymous hash to an hash, which is the same as saying my %h = {}; or my %h = 'a'; or my %h = 1;.    You need to assign a list with an even number of elements.

    In Example 2 you are assgning a list of eight elements to the hash.    Unfortunately two of the keys are the same as the other two keys so only the last two unique keys are saved to the hash.

    Example 3 is basically the same as Example 1.

      Thank you very much...that was helpful.
Re: Difference in Hash Declaration
by MidLifeXis (Monsignor) on May 07, 2012 at 13:47 UTC

    The only one that is syntactically valid is the second one, however, I don't believe that it is doing what you are expecting. Since the parens denote precedence, what Perl reads it as is:

    my %sham = ( 1 => "j", 2 => "b", 1 => "p", 2 => "b", );

    When assigning to hashes, later insertions with the same key end up replacing any earlier entries with the same key, leaving you with:

    my %sham = ( 1 => "p", 2 => "b", );

    This can be shown with the use of Data::Dumper or the like. I think what you are intending is:

    my @sham = ( # note the sigil { 1 => "j", 2 => "b", }, { 1 => "p", 2 => "b", }, );

    Data::Dumper (and any similar module) is a useful tool for visualizing nested data structures.

    --MidLifeXis

Re: Difference in Hash Declaration
by anazawa (Scribe) on May 07, 2012 at 08:13 UTC
    Parenthesis () creates LIST:
    ( 1 => 'j', 2 => 'b' )
    To create a hash, we substitute the LIST for %h:
    my %h = ( 1 => 'j', 2 => 'b' );
    Incidentally, LIST is different from ARRAY. To create an array, we substitute LIST for @a:
    my @a = ( 1 => 'j', 2 => 'b' );
      Parenthesis () creates LIST:
      print 1, 'b', 3, 'd', 5, 'f', "\n";

      I see a list there but I don't see any parentheses.

      my @stuff = map $_ + 2, 6, 7, 8, 9, 10;

      Ditto

      Parentheses are used for precedence.

      my %h = ( 1 => 'j', 2 => 'b' );

      There the assignment operator has higher precedence than the comma operator so the parentheses are required.

        I agree with you. Parentheses don't create LIST, are used for precedence. I'm glad you pointed out my mistake :)
Re: Difference in Hash Declaration
by Anonymous Monk on May 07, 2012 at 07:17 UTC

    Say it with me:

    { 'hashes', 'are', 'curly', 'ones' }

    [ 'arrays', 'are', 'square' ]

    ( 'lists are round' )

    using and understanding strict/warnings cuts your development time in half!

    #!/usr/bin/perl -- use strict;use warnings; use Data::Dump qw/ dd /; my %ro = { ( 1 => "j", 2 => "b", ), ( 1 => "p", 2 => "b", ), }; my %sham = ( ( 1 => "j", 2 => "b", ), ( 1 => "p", 2 => "b", ), ); my %bo = { { 1 => "j", 2 => "b", }, { 1 => "p", 2 => "b", }, }; dd \%ro; dd \%sham; dd \%bo; __END__ Reference found where even-sized list expected at - line 4. Reference found where even-sized list expected at - line 28. { "HASH(0x3f8c64)" => undef } { 1 => "p", 2 => "b" } { "HASH(0x99a3bc)" => undef }
      Thanks. This is useful.