First, use pop
to separate the value to assign from the keys. Then, you can use either of the following:
use Data::Diver qw( DiveVal );
my %hash;
DiveVal(\%hash, map $_, @keys) = $val;
or
sub dive_val :lvalue {
my $p = shift;
$p = ( $$p->{$_} ) for @_;
$$p
}
my %hash;
dive_val(\%hash, @keys) = $val;
dive_val
works by having $p
reference the next value to dereference and/or modify.
Pre-loop: $p references $hash (the anon scalar referencing %hash)
After loop pass 0: $p references $hash->{1}
After loop pass 1: $p references $hash->{1}{2}
After loop pass 2: $p references $hash->{1}{2}{3}
After loop pass 3: $p references $hash->{1}{2}{3}{4}
The extra level of indirection has many benefits.
- It removes the need to treat the last key specially.
- It removes the need to create the hash before it's dereferenced.
- It removes the need for the root to be a reference to a hash. Instead, any scalar can be the root, even an undefined one.
- It makes it easy to extend
dive_val
to support mixed array/hash structures.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…