我正在寻找一种更有效的方法来在perl中编写此affect
子例程:
#!/usr/bin/perl
use 5.010;
use strict;
my @keys = qw/foo bar baz/;
my %hash = ( foo => {babel => 'fish'} );
affect (\%hash, 42);
sub affect {
my $ref = shift;
$ref = $ref->{$keys[$_]} //= {} for (0.. $#keys - 1);
$ref->{$keys[$#keys]} = shift;
}
use Data::Dumper;
print Dumper \%hash;
预期结果:
$VAR1 = {
'foo' => {
'bar' => {
'baz' => 42
},
'babel' => 'fish'
}
};
我正在考虑这样的事情,但显然它不能像这样工作:
%hash{ @keys } = 42;
有什么想法吗?
答案 0 :(得分:5)
如果您真正传递密钥会更有效!我们让它同时成为一个左值子。
sub dive_val :lvalue {
my $p = \shift;
$p = \( $$p->{$_} ) for @_;
$$p
}
my %hash;
dive_val(\%hash, qw( foo babel )) = 'fish';
dive_val(\%hash, @keys) = 42;
此实施有两个额外的好处。
首先,您可以使用它来查看数据结构。
print(dive_val($hash, @keys), "\n");
其次,它会自动生成第一个参数。
my $hash;
dive_val($hash, @keys) = 42;
此功能已作为Data::Diver的DiveVal
存在。
use Dive::Val qw( DiveVal );
DiveVal(\%hash, map \$_, @keys) = 42;
affect
和dive_val
的流量比较:
affect
$ref
是对哈希的引用。
Pre-loop: $ref references %hash
After loop pass 0: $ref references %{ $hash{$key[0]} }
After loop pass 1: $ref references %{ $hash{$key[0]}{$key[1]} }
Post loop uses: $ref->{$key[2]}
dive_val
$p
是对标量的引用。
Pre-loop: $p references $hash
After loop pass 0: $p references $hash->{$key[0]}
After loop pass 1: $p references $hash->{$key[0]}{$key[1]}
After loop pass 2: $p references $hash->{$key[0]}{$key[1]}{$key[2]}
Post loop uses: $$p
dive_val
的方法更纯粹。
affect
不同)。 dive_val
以支持混合数组/哈希结构。