Is there a way to do the following while using only one data structure?
my %hash = (
"key1" => "value1",
"key2" => "value2",
"key3" => $hash{key1},
);
So basically, I want to set a hash's key value to another key value. I've tried the above syntax but get the following warning:
Global symbol "%hash" requires explicit package name at ...
I'm assuming this is because I'm trying to reference the hash before it's actually been created.
Why not make your own function:
use strict;
use warnings;
sub make_hash (@) {
my %h;
my @unresolved;
while ( @_ ) {
my ( $key, $value ) = splice( @_, 0, 2 );
next unless defined $value;
if ( not ref( $value )
and my ( $ref ) = $value =~ /^ref:\s*(.*\S)\s*$/
) {
if ( defined( my $v = $h{ $ref } )) {
$h{ $key } = $v;
}
else {
push @unresolved, [ $key, $ref ];
}
}
else {
$value =~ s/^lit://;
$h{ $key } = $value;
}
}
$h{ $_->[0] } = $h{ $_->[1] } foreach grep { exists $h{ $_->[0] }; } @unresolved;
return wantarray ? %h : \%h;
}
To demonstrate some of the power:
my %hash
= make_hash(
'key1' => 'value1'
, 'key2' => 'value2'
, 'key3' => 'ref:key1'
, 'key4' => 'lit:ref:key2'
, 'key5' => 'lit:lit:ref:key3'
);
The lit:
prefix covers the case of "What if I really wanted to pass a value that is a non-reference as 'ref:so-and-so'
? It also is recursive in answering, "What if I direly need to make a value 'lit:xzy'.
I've done this and I've also blessed a reference to a passed piece of data to a Lit
class or something along those lines.
sub Ref ($) { bless \shift, 'Ref' }
And then in the make_hash
routine you'd just check for ref( $value ) eq 'Ref'
. And specify it like the following:
my %hash
= make_hash(
'key1' => 'value1'
, 'key2' => 'value2'
, 'key3' => Ref 'key1'
);
There are many ways to make Perl act like you wish it did.