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

Q: What's the difference between a duck ?
A: One of its legs is both the same.

So ... I'm looking at 2 different ways of assigning a hash:
my %h1 = (FOO => 1, BAR => 2); my %h2 = %{{FOO => 1, BAR => 2}};
and wondering what the difference is.

What coding opportunities does the latter provide, that the former can't provide ? ... or is this just a case of tmtowtdi ?

No need to provide a detailed discourse ... a referral to relevant documentation should suffice. (I don't actually understand why/how the the assignment to %h2 in the above code works.)

Cheers,
Rob

Replies are listed 'Best First'.
Re: What's the difference between a hash ?
by davido (Cardinal) on Nov 19, 2006 at 07:09 UTC

    The first way is straightforward, and probably desirable under many circumstances. The second way is kind of inefficient. In the second method, you're creating an anonymous hash, referred to by a temporary hashref. That hashref is then dereferenced as a hash, and assigned to %h2.

    The second way takes an extra step. In the narrow context you've displayed it's completely unneeded. It's less memory and computationally efficient, and arguably less clear to the reader.

    However, that's not to say there arent times when an anonymous hashref is useful. Consider the following:

    my $href = { FOO => 1, BAR => 2 }; my_sub( $href ); sub my_sub { my $href = shift; # do something with the hash ref... }

    In other words, references and anonymous hashes are, theselves, useful. But the way you used them in your second example isn't.

    Relevant documentation: perlref, perlreftut, and perldsc.


    Dave

Re: What's the difference between a hash ?
by BrowserUk (Patriarch) on Nov 19, 2006 at 07:10 UTC

    The second varient is stupid.

    1. It builds one (anonymous) hash;
    2. flattens it to a list by dereferencing it in a list context;
    3. assigns the list to build a second named hash;
    4. and discards the anonymous hash.

    The first only does step 2.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Bah ... part of my problem was that I had tried replacing the anonymous hashref with a named hashref, and found it didn't work. Apparently, I had made some simple coding error, because the following does, in fact, work as expected:
      use warnings; use strict; my $h = {FOO => 1, BAR => 2}; my %hash = %{$h}; print $hash{FOO}, "\n"; print $hash{BAR}, "\n";
      Incidentally, that "stupid" way of assigning hashes was taken from the Makefile.PL that Inline::C autogenerates. (I guess that has something to do with the way that Inline::C determines its parameters.)

      Thanks guys.

      Cheers,
      Rob

        Unless there is something that you've omitted by the simplification for the OP example code, there is no utility at all in building a named hash from a constant list via an anonymous hash.

        In your modified example above, there is the potential for utility, though it is not realised. That of retaining a copy of the original (anonymous) hash. This only comes about because a reference to the anonymous hash is retained which it isn't in the OP.

        This allows modifications to be made to the copy whilst retaining the original. This can be used for setting defaults in object constructors and the like:

        package someclass; my $defaults = { foo=>1, bar=>23 }; sub new { my $class = shift; my %self = ( %{ $defaults }, @_ ); return bless \$self, $class; }

        Here keys foo and bar in $self will get the default values unless they are overidden by named arguments on the constructor, and $defaults remains unmodified.

        Though there is little merit in using a named anonymous hash rather than real hash unless $defaults is passed to a subroutine somewhere.

        ps. I didn't say it didn't work. Only that there was no point to it! ;)


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.