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

Hi monks,

I have a doubt in getting values in hash reference. Please see my by below code and comment and give me pour some idea about the code. I cannot understand this code, how it's working please some one give me an idea

"print @$hash_ref{'a', 'b'};"
#!/usr/bin/perl -w use strict; use warnings; use Data::Dumper; #Hash my %hash = ('a' => 1, 'b' => 2); #To print the two values i have mentioned keys print @hash{'a', 'b'}; #Hash Reference my $hash_ref = \%hash; #To print the two values i have mentioned keys i am getting error (Glo +bal symbol "@hash_ref" requires explicit package name) print @hash_ref->{'a', 'b'}; #Prints values without error print @$hash_ref{'a', 'b'};

Replies are listed 'Best First'.
Re: Getting values in Hash Reference?
by davorg (Chancellor) on Apr 24, 2006 at 11:13 UTC

    See perldoc perldata - in particular the section on slices (the section talks about array slices, but it's equally applicable to hash slices).

    Unfortunately, as you've found, you can't use hash slices with a hash reference and a dereferencing arrow.


    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: Getting values in Hash Reference?
by jonadab (Parson) on Apr 24, 2006 at 11:55 UTC

    Remember that a reference is a scalar, even if the thing it points to isn't. So $hash_ref is a scalar, even though it _points to_ a hash.

    You can't take a slice of a scalar. You can take a slice of an array (@foo[2,4,5]), or you can take a slice of a hash (@foo{'a','b','d'}), but a slice of a scalar doesn't make sense.

    However, you _can_ take a slice of a hash, so you _can_ take a slice of the hash that the reference points to. What you have to do is dereference it, to get to the hash, and then take the slice of that. There are several syntaxes you can use for this, but here's one:

    @{%$hash_ref}{'a', 'b'}

    Notice that I've used % to dereference, because the thing that the reference points to is a hash. (If it pointed to an array, I would dereference with @ or if it pointed to a scalar I'd use $ to do the dereferencing.) The extra set of braces is just to clarify what it is that I'm slicing with the @ symbol.

    update: It turns out that the hash slice notation is enough to dereference the hash reference, so the % isn't necessary (although it doesn't hurt anything), so the above could also be written thusly:

    @{$hash_ref}{'a', 'b'}

    However, in general, you would dereference a hash with % thusly:


    Also note that if you want to pull out just a certain hash value, you would dereference with a scalar $ sigil, thusly:


    If you need to use more complex syntax to refer to the hash reference, you then need the clarifying braces (like we used above with the slice):

    %{ some_expression_that_evaluates_to_a_hash_ref() }
    ${ some_expression_that_evaluates_to_a_hash_ref() }{$key}

    It is also possible to dereference with the -> arrow notation, but in that case everything on the left side of the arrow has to evaluate to a reference, which is then dereferenced and the operation on the right (usually subscripting) is performed on the result. So in your code, @hash_ref would need, by itself, to be a reference, but it's not; it's an array (which does not happen to be defined). So you need to put the reference on the left side of the arrow:


    Then on the right side you put your operation, such as subscripting.


    However, since braces in this case would normally mean ordinary hash subscripting, not slicing, this notation does not work for hash slicing.

      *SIGIL*{} is used to dereference, so you don't need the extra %.

        This gives me a great idea for an obfuscation involving nested hash slice dereferencing of nested anonymous hash references...


        If I nest that sort of nonsense about eight levels deep I might have something genuinely confusing.

        It doesn't work without a qualifier. If you'll use the hash you need the %. If you'll use a value (follow the dereferenced hash by {Key}), you'll need the $.