Two questions regarding the following code :
%h1 = {
'key1' => ( 1, 2, 3 ),
'key2' => ( 4, 5, 6 )
};
%h2 = {
'key1' => [ 1, 2, 3 ],
'key2' => [ 4, 5, 6 ]
};
print $(@h1{'key2'})[1];
Q1 : What is the difference between h1 and h2? Please don't say 'one is a hash of lists and another hash of arrays'... Rather, I want to know what that translates to in terms of usage.
Q2 : Why does the the reference $(@h1{'key2'})[1]
in the print statement not compile? This is my thinking : I want access the array/list corresponding to 'key2' : @h1{'key2'}
. Then I want to access the scalar at the index of 1 in that list/array : $(@h1{'key2'})[1]
. Why is this wrong ? This variable referencing stuff is confusing.
Neither of those work like you think. use strict and use warnings always.
%h1 = {
'key1' => ( 1, 2, 3 ),
'key2' => ( 4, 5, 6 )
};
You're trying to assign a hashref ( {} construct ) to a hash. It gets stringified into a scalar and is used as a key in %h1, with a value of undef. In addition, cause you're using lists ( () construct), it gets flattened and you're creating the hash:
%href = ( key1 => 1,
2 => 3,
key2 => 4,
5 => 6,
);
In the latter case, you correctly create your hash with array refs ( [] construct), but you're still assigning a href to the hash. You want to do:
%h1 = (
'key1' => [ 1, 2, 3 ],
'key2' => [ 4, 5, 6 ]
);
This creates %h1 in list context and your values in scalar context via reference.
The difference: they're both wrong! :)
Lists are flat structures; you can't have lists of lists, you just get a (one-dimensional) list back.
References are scalars. So %h1 = { ... }
doesn't make sense. What you're doing is just assigning a one-element list to %h1
, which gets stringified and turned into a key. This is equivalent to
%h1 = ( 'HASH(0x1fb872a0)' => undef );
where the key is the stringified version of whatever memory address held that hash reference.
To make a hash of arrays, do this:
my %h1 = ( key1 => [ 1, 2, 3 ], key2 => [ 4, 5, 6 ] );
If you want a reference to a hash of arrays, you can use:
my $ref = { key1 => [ 1, 2, 3 ], key2 => [ 4, 5, 6 ] };
or
my $ref = \%h1;
Finally, to access your structure elements, you can use:
print $h1{key2}[1];
or
print $ref->{key2}[1];
In the latter case we use the ->
operator to dereference the structure. For subsequent levels, ->
is assumed, but you can also write
print $ref->{key2}->[1];
if you find that clearer.
To get the complete structure back from the reference (e.g. to use keys
) you need to use another form of dereferencing:
my @keys = keys %$ref; # or more explicitly %{ $ref }
To get at the full inner structure, it's the same thing:
my @a2 = @{ $ref->{key2} };
All of this is covered in full detail in the following excellent Perl docs:
and others.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With