Search code examples
perlperl-data-structures

Unable to properly merge hashes


I currently have the following

# $dog, $cat, $rat are all hash refs

                my %rethash = ('success' => 'Your Cool'); 

                my %ref ={ 'dog' => $dog,  'cat' => $cat,  'mouse' => $rat,
                                'chicken' => ''  };

                my $perlobj = ( \%ref,\%rethash );      

When $perlobj is dumped this is the result

 $VAR1 = {
      'success' => 'Your Cool'
    };

However when warnings are enabled I get the following message

Useless use of reference constructor in void context at ..

I realize there is something terribly wrong with how %ref is assigned using {}, What is wrong with this code? I can't seem to get rid of this warning....

EDIT: Ok I think I figured out whats going on,

my $perlobj = ( \%ref,\%rethash );

This does not merge but results in $perlobj becoming a reference to %rethash, this is obvious after reading your responses.


Solution

  • What RobEarl is saying is correct. I'll give an explanation of that and add some more stuff.

    Your variable name %ref and the fact that you are using {} kinda implies you want a reference here.

    Let's take a look what value we will have in %ref. Consider this example.

    use strict; use warnings;
    use Data::Printer;
    my %foo = { key => 'value' };
    p %foo;
    

    This will throw a warning Reference found where even-sized list expected on my Perl 5.20.2. The output will be:

    {
        HASH(0x7e33c0)   undef
    }
    

    It's a hash with a hashref as the key and undef as a value. HASH(0x07e33c0) is what you get when you look at a hash reference without dereferencing it. (The {} are there because Data::Printer converts the hash to a hashref).

    Back to your code, the correct sigil for a reference is $. It does not matter what kind of reference it is. The reference is always a scalar (a pointer to the place in memory where the hash/array/something) is stored.

    my $ref = { 
      dog     => $dog,
      cat     => $cat,
      mouse   => $rat,
      chicken => '', # maybe this should be undef?
    };
    

    Now you've got a hashref with the values of $dog, $cat, $rat and an empty string.

    Now you're assigning a variable named $perlobj, which implies it's an object. Instead you are assigning a scalar variable (the $ makes it a scalar) with a list. If you do that, Perl will only assign the right-most value to the variable.

    my $foo = (1, 2, 3); # $foo will be 3 and there's a warning
    

    You are assigning a list of two references. The first one is disregarded and only \$rethash gets assigned. That works because conveniently, $perlobj is a scalar, and references are also scalars. So now $perlobj is a reference of %rethash. That's why your Data::Dumper output looks like %rethash.


    I'm not sure what you want to do, so I cannot really help you with that. I suggest you read up on some stuff.

    • perlreftut is useful to learn how references work
    • If you want to do Object Oriented Programming, check out Moose
    • It might also be useful to just go get a book to learn a bit more about basic Perl. Learning Perl by Randal L. Schwartz and Beginning Perl by Curtis Poe are both very good for that