这似乎是一件奇怪的事情,但如何在"内部"哈希时引用哈希?以下是我要做的:
我有一个散列,末尾有一个子,比如:
my $h = { A => [...], B => [...], ..., EXPAND => sub { ... } };
我希望实现EXPAND
,看看这个散列中是否存在密钥C
,如果存在,则插入另一个键值对D
。
所以我的问题是,如何在不使用哈希的变量名的情况下将对该哈希的引用传递给子?我预计需要对一些散列执行此操作,并且我不想一直更改子以引用它当前所在的散列的名称。
这里有一些嵌套的数组引用,而不是散列。假设你的意思是你有这样的东西:
my $h = { A => {...}, B => {...}, ..., EXPAND() };
在这种情况下,不能从$h
自己的定义中引用它,因为$h
在表达式完全求值之前是不存在的。
如果你满足于把它做成两行,那么你可以这样做:
my $h = { A=> {...}, B => {...} };
$h = { %$h, EXPAND( $h ) };
一般的解决方案是编写一个函数,给定一个哈希和一个扩展该哈希的函数,返回该哈希并添加扩展函数。我们可以在扩展函数中关闭该哈希,这样就不需要在其中提及该哈希的名称。如下所示:
use strict;
use warnings;
use 5.010;
sub add_expander {
my ($expanding_hash, $expander_sub) = @_;
my $result = { %$expanding_hash };
$result->{EXPAND} = sub { $expander_sub->($result) };
return $result;
}
my $h = add_expander(
{
A => 5,
B => 6,
},
sub {
my ($hash) = @_;
my ($maxkey) = sort { $b cmp $a } grep { $_ ne 'EXPAND' } keys %$hash;
my $newkey = chr(ord($maxkey) + 1);
$hash->{$newkey} = 'BOO!';
}
);
use Data::Dumper;
say Dumper $h;
$h->{EXPAND}->();
say Dumper $h;
请注意,我们正在创建$h
,但add_expander
调用中没有提到$h
。相反,传递到调用中的子期望它要扩展的哈希作为它的第一个参数。在子上的散列上运行add_expander
会创建一个闭包,该闭包将记住扩展器与哪个散列相关联,并将其合并到散列中。
该解决方案假设扩展哈希时应该发生的事情可能因主题哈希而异,因此add_expander
采用任意的sub。如果您不需要该自由度,可以将扩展sub合并到add_expander
中。
正在构建的哈希(可能)发生在EXPAND()
运行之后。我可能会使用这样的东西:
$h = EXPAND( { A=>... } )
其中EXPAND(...)
返回修改后的hashref,如果原始hashref需要保持原样,则返回克隆。