Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

using hash key as hash value ...

by blueflashlight (Pilgrim)
on Oct 02, 2001 at 04:26 UTC ( #116030=perlquestion: print w/replies, xml ) Need Help??
blueflashlight has asked for the wisdom of the Perl Monks concerning the following question:

hi, monks ...

Trying to figure out why this doesn't work ...
my %media = ( bond => "USLetter:Plain:white:75", letter => $media{bond}, plain => $media{bond} );

I also tried using references (i.e., "\$media{bond}") as the value; that didn't work either.

Thanks, --Sandy

Replies are listed 'Best First'.
Re: using hash key as hash value ...
by George_Sherston (Vicar) on Oct 02, 2001 at 04:37 UTC
    The reason it doesn't work is that you use $media{bond} before you've finished defining %media. Run under strict, therefore, it fails with
    Global symbol "%media" requires explicit package name
    You get that error for both the lines where you use $media{bond} within the definition of %media. But this works fine:
    my %media = ( bond => "USLetter:Plain:white:75", ); $media{letter} = $media{bond}; $media{plain} = $media{bond};

    Hey! Another reason to use strict!

    George Sherston
      thanks ... actually, I did (and always) 'use strict;' but I just pasted a snippet of the code above, not the whole thing. Your explanation is great. Thanks.

        Sorry to doubt you, Sibling... I have the zeal of the converted sinner :)

        George Sherston
Re: using hash key as hash value ...
by japhy (Canon) on Oct 02, 2001 at 04:36 UTC
    At the time you access the value $media{bond}, it does not yet exist. To get around this, you can do something like:
    $_ = "a:default:value" for @hash{'key1', 'key2', 'key3'}; # or $hash{$_} = "a:default:value" for 'key1', 'key2', 'key3'; # or @hash{'key1', 'key2', 'key3'} = ("a:default:value") x 3;
    If you actually want one key of a hash to be an alias to another key, you'll have to do some tie() magic.

    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      yow. that's more involved then I wanted to get into. (Actually, the reason I'm trying to do what I'm trying to do is to make my code "easy" to read for other people at my org. who may need to modify it.)

      Tie::AliasHash looks cool, though ... perhaps I'll try it out sometime.

      thanks! --sandy
Re: using hash key as hash value ...
by pjf (Curate) on Oct 02, 2001 at 04:39 UTC
    It doesn't work because your hash hasn't been created at the time you try to assign to the letter and plain keys. If you're using strict, perl will complain loudly about that.

    You can do what you're after, but you need to do it in two steps. The first step is to create your hash with the bond key in it, and the second step is to fill in the other values. For example:

    my %media = (bond => "USLetter:Plain:white:75"); %media = (%media, letter => $media{bond}, plain => $media{bond});
    This does what you're after. Putting %media as the first entry when re-assigning the hash makes sure that the old values are put back in.

    Of course, TMTOWTDI. The following is probably faster (as we're not copying the hash back into itself), and more compact, but more difficult to understand.

    my %media = (bond => "USLetter:Plain:white:75"); @media{qw/letter plain/} = @media{qw/bond bond/};
Re: using hash key as hash value ...
by jryan (Vicar) on Oct 02, 2001 at 04:39 UTC

    Its because %media hasn't been declared completely yet. It would be like trying to do this:

    my $var = "blah".substr($var, 0, 2);

    Just because part of it is declared, doesn't mean the whole thing is. If you must reuse the code, store it in an earlier variable:

    my $temp = "USLetter:Plain:white:75"; my %media = ( bond => $temp, letter => $temp, plain => $temp );
Re: using hash key as hash value ...
by blackjudas (Pilgrim) on Oct 02, 2001 at 04:39 UTC
    The hash %media hasn't been scoped yet, the interpreter executes the 'line' at the semicolon. Therefore %media doesn't exist until perl sees the semicolon. In your case, I would suggest breaking out the assignments into different instructions. Such as the following:

    my %media = ( bond => "USLetter:Plain:white:75" ); $media{'letter'} = $media{'bond'}; $media{'plain'} = $media{'bond'};

    Though there's probably better ways to do it through looping etc, it all depends on what you need done.
      I'll probably do it the way you suggest. It seems like it's "easiest" on the eyes.

      thanks, --sandy

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://116030]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2018-06-20 06:35 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (116 votes). Check out past polls.