tags:

views:

121

answers:

3

Let's say I have a hashref constant like the following:

use constant DOGS => {
    Lassie => 'collie',
    Benji  => 'mutt',
    Scooby => 'great dane',
    Goofy  => '???'
};

How can I dereference it properly to get say.. they keys out of it?

warn ref DOGS; # HASH at untitled line 12.
warn keys( %{DOGS} ); # Warning: something's wrong (empty list)
warn keys( DOGS ); # Type of arg 1 to keys must be hash (not constant item)

The following is the only way I can seem to make it work:

my $dogs = DOGS;
warn keys( %$dogs ); # LassieBenjiGoofyScooby at untitled line 15.

What am I doing wrong?

A: 

Force it into list context...

warn keys(%{(DOGS)});
Amit
-1 for cargo cult. It is not forcing list context but breaks hash key name Perl magic.
Hynek -Pichi- Vychodil
+9  A: 

This will usually work for you:

%{DOG()}

Constants are generally just subs. But for ease (and looks), you might prefer to use Readonly, as suggested in PBP.

Readonly::Hash my %DOG => 
    ( Lassie => 'collie'
    , Benji  => 'mutt'
    , Scooby => 'great dane'
    , Goofy  => '???'
    );
Axeman
Perfect - and good extra information. Thanks!
makenai
+5  A: 

Perldoc is your friend: perldoc constants

You can get into trouble if you use constants in a context which automatically quotes barewords (as is true for any subroutine call). For example, you can't say $hash{CONSTANT} because "CONSTANT" will be interpreted as a string. Use $hash{CONSTANT()} or $hash{+CONSTANT} to prevent the bare- word quoting mechanism from kicking in. Similarly, since the "=>" operator quotes a bareword immediately to its left, you have to say "CONSTANT() => 'value'" (or simply use a comma in place of the big arrow) instead of "CONSTANT => 'value'".

warn keys %{DOG()} should do the trick.

Logan
Good to know. Thanks!
makenai