Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an empty Perl hash have one key?

Tags:

key

hash

perl

size

The standard googleable answer to "How do I find out the size of a hash in Perl?" is "take the size of keys(%hash)":

my %h = {};
print scalar (keys (%h));

This prints '1'. I was expecting zero. On the other hand. Similarly,

my %h = {};
$h{"a"} = "b";
$h{"x"} = "y";
print scalar keys (%h);
print "\nKey: $_" for (keys %h);

Prints:

3

Key: a

Key: x

Key: HASH(0x229e8)

Where has this extra value come from?

like image 462
spraff Avatar asked Apr 12 '11 09:04

spraff


4 Answers

$ perl -Mwarnings -e'my %h = {}'
Reference found where even-sized list expected at -e line 1.

strict and warnings are included with Perl for very good reasons. There is no reason not to use them.

Even better, add diagnostics into the mix too:

$ perl -Mwarnings -Mdiagnostics -e'my %h = {}'
Reference found where even-sized list expected at -e line 1 (#1)
    (W misc) You gave a single reference where Perl was expecting a list
    with an even number of elements (for assignment to a hash). This usually
    means that you used the anon hash constructor when you meant to use
    parens. In any case, a hash requires key/value pairs.

        %hash = { one => 1, two => 2, };    # WRONG
        %hash = [ qw/ an anon array / ];    # WRONG
        %hash = ( one => 1, two => 2, );    # right
        %hash = qw( one 1 two 2 );      # also fine
like image 109
Dave Cross Avatar answered Oct 09 '22 03:10

Dave Cross


This has bit me before too.

my %h = ();

Note the use of () instead of {}.

Explanation: The value {} is a reference to a hash, rather than a hash itself. In Perl, a reference is a kind of scalar value, and the assignment to %h has special processing for assigning a single scalar value. It stringifies the scalar (giving you the string HASH(0x229e8) in your case), and associates that key with the value undef.

When using (), the assignment from list to hash creates key/value pairs from pairs in the list, and since () is empty, the hash %h becomes empty.

like image 25
Greg Hewgill Avatar answered Oct 09 '22 04:10

Greg Hewgill


{} is a reference to an anonymous hash. So my %h = {} is equivalent to my %h = ({} => undef).

Perl requires hash keys to be strings, so when you use a reference as a key, Perl uses the reference's string representation (HASH(0x229e8)).

like image 34
Eugene Yarmash Avatar answered Oct 09 '22 02:10

Eugene Yarmash


use Data::Dumper;

my %h = {};
warn Dumper \%h;

%h gets assigned with a hash reference as the key and undef as the value.

Output:

$VAR1 = {
          'HASH(0x8683830)' => undef
        };

As rafl suggested, the warnings pragma would have caught this. Look at Greg Hewgill's answer for the corrected code.

like image 35
Alan Haggai Alavi Avatar answered Oct 09 '22 04:10

Alan Haggai Alavi