biketastic has asked for the wisdom of the Perl Monks concerning the following question:

Ok, so I've got a method that returns a hash like this:

return %{$obj->{$attr_name}};

And when I want to access this hash I can do this:

my %hash = $obj->method();

Splendid.

So why can't I be Lazy and do this?

foreach my $item (keys %{$obj->method()} {

My guess is that the hash gets flattened into list context by the return and somehow doesn't get coerced back into a hash by the keys function, whereas explicitly assigning it to a hash does coerce it. Anyone care to enlighten me?

Cheers,
Bill.

Replies are listed 'Best First'.
Re: iterating returned hashes
by broquaint (Abbot) on Sep 19, 2002 at 09:59 UTC
    So why can't I be Lazy and do this?
    Because you're trying to dereference the hash that $obj->method returns, which won't work seeing as how it's already a hash. You could just change your code so that you can dereference your return value e.g
    # assuming $obj->{attr_name} holds a hashref return $obj->{attr_name}; } # code passes foreach my $item (keys %{ $obj->method() }) {
    My guess is that the hash gets flattened into list context by the return and somehow doesn't get coerced back into a hash by the keys function
    A hash is indeed flattened to a list in list context, which is provided by your hash assignment in your second example. However keys expects a % sigil, so while you are returning a hash1 from $obj->method keys is none the wiser. So you have to enforce the sigil by either using a hash or dereferencing a hashref e.g
    my %hash = qw(foo bar baz quux); my $hashref = \%hash; my @list = qw(ichi ni san shi); my $lisref = \@list; keys %hash; # valid keys %$hashref; # valid keys %{{@list}}; # valid keys %{{@$listref}}; # valid keys $hashref; # invalid keys %{@list}; # invalid

    HTH

    _________
    broquaint

    update: added further clarification about hashes
    1 you're not really returning a hash, just a list which is being stuffed into a hash

Re: iterating returned hashes
by blakem (Monsignor) on Sep 19, 2002 at 10:20 UTC
    The syntax %{ ... } is expecting a hash ref, but you're handing it a list. You'll need to enclose your list in (another) set of curly brackets to get it to do what you want:
    # anon hash bracket \ # | # grouping bracket \ | # | | # V V print "$_\n" for keys %{ { returnlist() } }; sub returnlist { 1..10 }

    -Blake

Re: iterating returned hashes
by biketastic (Initiate) on Sep 19, 2002 at 10:35 UTC
    Thanks for your enlightenment guys.

    Bill.