get hahes key to string in perl

Viewed 112

I do not understand why $test is '1' and not 'foo'. Is there any way to write 'foo' (written in %hash) to $test?

#/usr/bin/perl
use warnings;
use strict;
use utf8;

my %hash;
$hash{'test'} = {'foo' => 1};

print keys %{$hash{'test'}}; #foo
print "\n";
print values %{$hash{'test'}}; #1
print "\n";
print %{$hash{'test'}}; #foo1
print "\n";

# here is the part I do not understand
my $test = keys %{$hash{'test'}};
print "$test\n"; #1 but why? I was expecting #foo

How can I push 'foo' in $test?

3 Answers

keys() returns a list. But your assignment to a scalar (my $test = keys ...) puts it into scalar context. Therefore it is evaluated to the length of the list, which is 1 in your case.

my $test = keys %{$hash{'test'}};

When assigning a list like keys returns to a scalar, what's assigned is the length of the list. Which is 1 in this case.

When the return value from a Perl function confuses you, it's always worth checking the documentation for that function - paying particular attention to the section talking about how the return value varies in different contexts.

The very start of perldoc -f keys says this (emphasis mine):

keys HASH
keys ARRAY

Called in list context, returns a list consisting of all the keys of the named hash, or in Perl 5.12 or later only, the indices of an array. Perl releases prior to 5.12 will produce a syntax error if you try to use an array argument. In scalar context, returns the number of keys or indices.

You're assigning the results of the expression to a scalar variable. The expression is, therefore, evaluated in scalar context and you get the number of keys in the hash (i.e. 1).

To fix that, force the expression to be evaluated in list context by putting parentheses around the variable:

my ($test) = keys %{$hash{'test'}};
Related