nurp
nurp

Reputation: 1275

How to merge two hashes returned from sub, in Perl

I am trying to merge two hashes. But they are return values from functions. How can I dereference the return values inline? I don't want to use extra variables such as my $pos = makePos();

use v5.8.8;

use strict;
use warnings;

sub _makePos
{
    my $desc= {
        pos50  => {unit => 'm', desc => 'position error' },
        pos95  => {unit => 'm', desc => '95% position error' }
    };
    return $desc;
}

sub _makeVel
{
    my $desc= {
        vel50  => {unit => 'm/s', desc => 'velocity error' },
        vel95  => {unit => 'm/s', desc => '95% velocity error' }
    };
    return $desc;
}

my $descs = {_makePos(), _makeVel()};
use Data::Dumper;
print Dumper($descs);

this prints only the hash returned from _makeVel. how does it work?

$VAR1 = {
          'HASH(0x21ea4a0)' => {
                                 'vel50' => {
                                              'desc' => 'velocity error',
                                              'unit' => 'm/s'
                                            },
                                 'vel95' => {
                                              'unit' => 'm/s',
                                              'desc' => '95% velocity error'
                                            }
                               }
        };

Upvotes: 1

Views: 130

Answers (2)

Dave Cross
Dave Cross

Reputation: 69314

Actually, your original solution did print both of the hashes, but the first one was "stringified" as it was being used as the key of your hash. It's there as HASH(0x21ea4a0).

I see you have a solution, but it might be worth explaining what was going wrong and why your solution fixed it.

Your two subroutines don't return hashes but, rather, hash references. A hash reference is a scalar value that is, effectively, a pointer to a hash.

A hash is created from a list of values. Your code that creates your news hash (actually, once again, a hash reference) is this:

my $descs = {_makePos(), _makeVel()};

This is two scalar values. The first is used as a key in the new hash and the second is used as the associated value - hence the results you get from Data::Dumper.

What you actually want to do is to "dereference" your hashes and get back to the actual hashes. You can dereference a hash using the syntax %{ ... }, where the ... is any expression returning a hash reference. And that's what you've done in your solution. You dereference the hash references, which gives you a list of key/value pairs. The pairs from the two dereferenced hashes are then joined together in a single list which is used to create your new, combined, hash.

I should point out that there's a danger in this approach. If your two subroutines can ever return references to hashes that contain the same key, then only one version of that repeated key will appear in the combined hash.

Upvotes: 1

nurp
nurp

Reputation: 1275

changing this line as

my $descs = {%{_makePos()}, %{_makeVel()}};

worked!

Upvotes: 2

Related Questions