http://www.perlmonks.org?node_id=653371

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

Hi Monks

I am creating a script using what I think are object oriented coding techniques. I am not able to get hash variables working properly. Could one of you let me know what I am missing here that would make my second print statement work properly.
my %BldEnv = ( "TTT2" => { VersionOne => "one", VersionTwo => "two", VersionThree => "three", VersionFour => "four", } ); # commented line works #print "$BldEnv{TTT2}{VersionOne}\n"; # uncommented line doesn't work print "$BldEnv->{TTT2}->{VersionTwo}\n";
I got 99 problems, but a @%$()_ ain't one.

Replies are listed 'Best First'.
Re: Using OO hash
by moritz (Cardinal) on Nov 27, 2007 at 21:11 UTC
    There is no OO involved in your example.

    %BldEnv is a plain hash, and the values can be accessed with the $hash{$key} syntax.

    The arrow -> is for references to hashes, blessed or not.

      Okay, I will use the first version. Thanks for the quick response.

      I got 99 problems, but a @%$()_ ain't one.
Re: Using OO hash
by meraxes (Friar) on Nov 27, 2007 at 21:53 UTC

    As moritz said, this isn't OO, but the second line will work with one small modification:

    print "$BldEnv{TTT2}->{VersionTwo}\n";

    Your version didn't work because the first -> was trying to dereference $BldEnv as though it were a reference to a hash. But WAIT! $BldEnv doesn't exist! You declared %BldEnv. Different animal! Despite using the $ sigil to get at hash values, when you added the -> after it, Perl was looking for a SCALAR variable and ignoring the HASH that you defined!

    Perl's syntactic sugar allows you to get around derefencing the 'TTT2' hash using ->. As such, the first one is better.

    Further to this, you really don't need to do string interpolation... can get a little messy with multi-level data structures. You could just do:

    print $BldEnv{TTT2}{VersionTwo},"\n";

    That way the variable is easier to see and prevents a number of interpolation pitfalls. If you're feeling adventurous, you could install the Perl6::Say module so you don't have to append that "\n" to the end like so:

    use Perl6::Say; say $BldEnv{TTT2}{VersionTwo};

    The "\n" is auto-appended by say.

    What you should _definately_ always do do is begin each script with:

    use strict; use warnings;

    This would have thrown an error on your last print statement telling you that you that $BldEnv hadn't been declared, cluing you in that you're doing something wrong.

    Happy Perl-ing!

    update: expanded on difference between $BldEnv{key} and $BldEnv->{key}.

    update the second: fixed errorneous variable naming.

    --
    meraxes