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

I have studied the Lore of the Perl Monks, and found much to recommend it, but not the answer to my question. I want to combine two hashes into a third. The following works for my needs, but I would like to know if it is guaranteed to work, or merely coincidental.
%a = (font => 'Arial', size => 10, bold => 0); %b = (size => 12); %fmt = (%a, %b);
I want the final hash to have (font=>'Arial',size=>12,bold=>0) so that the values in %b overwrite values in %a where necessary. I'd like to be sure that in future versions of Perl, %a won't suddenly decide to start overwriting %b. I don't think it should make a difference, but I don't actually plan to create the third hash explicitly; instead, I'll use it in a function call:
$object->write( 'Some Stuff', $object2->format( %a, (size => 12)) );
My hashes are small and insignificant, yet dear to me. But because they are small I am more concerned with shortness and clarity of the code than with raw efficiency.

Replies are listed 'Best First'.
Re: Simple concatenation of hashes
by sauoq (Abbot) on Aug 15, 2003 at 00:36 UTC

    Hrm. I don't know where or if it is documented... but I'm somehow very sure that the last value associated with a particular key is always the one that is kept. Given the way list flattening works, that means that, yes, %fmt = (%a, %b); will always result in %b overriding %a.

    Even though I couldn't find anything in the documentation, I did find several core module that apparently rely on this feature. I very much doubt it will ever be changed (on purpose) as it would undoubtedly break lots of code. If plans were made to change it, it would be deprecated long before it were actually changed.

    -sauoq
    "My two cents aren't worth a dime.";
    
Re: Simple concatenation of hashes
by chromatic (Archbishop) on Aug 15, 2003 at 01:00 UTC

    I can't come up with a situation where this is not what you want. Consider:

    $a = 1; $a = 2; print "\$a is $a\n"; $a[0] = 1; $a[0] = 2; print "\$a[0] is $a[0]\n"; $a{key} = 'value'; $a{key} = 'newvalue'; print "\$a{key} = $a{key}\n";

    While, of course, you can't rely on the keys of %a coming out in any particular order, why would you expect the keys of %b to come out before the keys of %a?

    If it ever changes, yes, it's a bug in Perl. It won't change.

      I agree that it's the logical behavior. But I think there's a difference between your examples and mine: in your examples, you are comparing two different statements, which have a definite execution order. In this case, you have a list, which does have a definite order -- in     %c=(%a, %b); the keys and values of %b come after the keys and values of %a. But the question is whether that order plays a predictable role in the conversion of the list into a hash.

      Common sense says that it should. But common sense is not always a predictor of future behavior.

      Sorry about the double replies. I'd remove one of them, except that I accidentally made them anonymously and so can't edit them.
Re: Simple concatenation of hashes
by thelenm (Vicar) on Aug 15, 2003 at 06:38 UTC

    I can't seem to find it in the documentation, either, but I know this technique can be used for providing default parameter values for a subroutine, e.g.

    { my %defaults = ( foo => 'bar', baz => 'quux' ); sub mysub { my %args = (%defaults, @_); # do something cool... } }

    where the %defaults hash provides default arguments that are overwritten by anything in @_. Since a hash is flattened in this context just as an array, the behavior should be the same.

    -- Mike

    --
    XML::Simpler does not require XML::Parser or a SAX parser. It does require File::Slurp.
    -- grantm, perldoc XML::Simpler

Re: Simple concatenation of hashes
by gholley (Initiate) on Aug 15, 2003 at 00:07 UTC
    Here's a related question, perhaps suitable for meditation: If I initialize a hash with redundant keys, do I get predictable results? That is, are the following two examples equivalent?
    %a = (one => 'eins', two => 'zwei', three => 'drei', one => 'uno'); %b = (one => 'eins', two => 'zwei', drei => 'drei'); $b{one} = 'uno';
Re: Simple concatenation of hashes
by esh (Pilgrim) on Aug 15, 2003 at 00:19 UTC

    I have long running, serious (multi-million dollar/year) commercial systems depending on the behavior you are seeing (last key wins) so my vote is that it continue this way into the future.

    I eagerly await a response from one who can provide an authoritative answer.

    Update: Whew!

    -- Eric Hammond