" /> " /> "/>

Can't use string ("test_value") as a HASH ref while "strict refs" in use at main.pl line 23

55 Views Asked by At

Can't use string ("test_value") as a HASH ref while "strict refs" in use at main.pl line 23.

use strict;
use warnings;

my $config = {'%test_value' => {'value' => '1'}};
    
my $args = 'test_value';    

print $$config{%$args}{'value'};

I'm trying to use the variable/argument for hash reference

1

There are 1 best solutions below

0
Grobu On
my $config = {'%test_value' => {'value' => '1'}};

The $config variable contains a reference to an anonymous hash, which also contains a reference to another anonymous hash :

$config --> anonymous_hash1:
              key   =   "%test_value"
              value --> anonymous_hash2:
                          key   = "value"
                          value = "1"

To de-refence such a variable, you can do:

print $$config{'%test_value'}, "\n";

or (using the arrow operator):

print $config->{'%test_value'}, "\n";

This should print something like HASH(0x4151e59ab6b7) (type of data structure and memory address of second anonymous hash).

You can chain the dereferencing syntax to access embedded data:

print $$config{'%test_value'}{'value'}, "\n";

or, with arrow operator:

print $config->{'%test_value'}->{'value'}, "\n";

When you write

my $args = 'test_value';    

print $$config{%$args}{'value'};

... the %$args expression is not equivalent to the '%test_value' key. The key you defined was of type string, and %$args evaluates to something completely different. Unquoted "%" symbol has a special meaning in Perl syntax, it is known as a sigil, and it introduces "hash context" to the following variable name / reference.

For example, if you take the following declarations:

my %my_hash = ( foo    => 'bar',
                hello  => 'world',
                number => 42 );

my $hash_ref = \%my_hash;

$my_hash{'foo'} and $$hash_ref{'foo'} would both return 'bar'.

$my_hash{'foo'} can be understood as "I need to access a scalar value (because of the leading $ sigil) stored in key "foo" of hash "my_hash". Similarly, $$hash_ref{'foo'} means "I need to access a scalar value stored in key "foo" of the hash referenced by variable $hash_ref. The hash sigil (%), contrary to the scalar one ($), allows to operate on the whole hash data structure, e.g. you can use it with the delete, exists, each, keys and values functions, which expect a hash argument.

Example:

foreach (keys %my_hash) { print "my_hash{$_} = $my_hash{$_}\n"; }

will produce:

my_hash{hello} = world
my_hash{number} = 42
my_hash{foo} = bar

... and foreach (keys %$hash_ref) ... will produce the same output!

So when you wrote %$args, Perl probably understood it as "consider the hash data structure referenced by variable $args", but $args contained a string, not a hash reference.


This is a complex topic and my understanding of it is probably very superficial and naive. See https://perldoc.perl.org/perlref and https://perldoc.perl.org/perlreftut for authoritative documentation.

Hope that helped ^^