Reputation: 11
I hope I've stated that subject correctly. I have a hash of hashes that I've built from reading a file. The outer hash is groups, then the inner hash is parameters within that group. Each parameter value can either be a scalar or array, and the arrays can start at either zero or one.
I've written a subroutine that returns the value of a parameter. The calling function has to figure out whether the returned value is a scalar or an array. Works fine for scalars. Returns a reference to an array for array values (looks like ARRAY(0x004f00)
). Using Data::Dumper
spits out data that looks like an array, but I can't figure out how to dereference it in the code. Can someone point to what I'm doing wrong?
%HoH = (
flintstones => {
husband => "fred",
possessions => [ undef, "car", "record player", "rock" ],
pal => "barney",
pets => [ "bird", "dinosaur" ],
},
);
get_value("possessions");
sub get_value {
my $what_i_want = shift;
@groups = keys(%HoH);
foreach my $group ( @groups ) {
foreach my $param ( keys( %{ HoH {group} } ) ) {
if ( $param eq $what_i_want ) {
return $HoH{$group}{$param};
}
}
}
}
The caller assigns the return value to an array, @return
, so in the case of a scalar it should put the value in $return[0]
.
In the case of an array, it should populate the array. When I call Dumper
, it prints out scalars in single quotes and arrays in square brackets, as it should. However, when I use scalar(@return)
to check the size of the array, it returns 1.
I've tried dereferencing the return statement using square brackets at the end to see if I could even get a scalar returned, but no luck.
Upvotes: 1
Views: 991
Reputation: 126742
You don't show the subroutine being called in context, but a quick fix would be to put this after the call
@return = @{ $return[0] } if ref $return[0]
You're missing the point of hashes. You can access the correct element of the parameter hash by using $what_i_want
as a hash key
I suggest you change your subroutine code to look like this
for my $group ( keys %HoH ) {
my $ret = $HoH{$group}{$what_i_want};
return unless defined $ret;
return ref $ret ? @$ret : $ret;
}
That way it will never return a reference
Here's your complete program modified as I suggested
use strict;
use warnings 'all';
my %HoH = (
flintstones => {
husband => "fred",
possessions => [ undef, "car", "record player", "rock" ],
pal => "barney",
pets => [ "bird", "dinosaur" ],
},
);
my @return = get_value('possessions');
use Data::Dump;
dd \@return;
sub get_value {
my ($wanted) = @_;
for my $group ( keys %HoH ) {
my $ret = $HoH{$group}{$wanted};
if ( defined $ret ) {
return ref $ret ? @$ret : $ret;
}
}
return;
}
[undef, "car", "record player", "rock"]
Upvotes: 2