在Perl中,我学习如何取消引用“函数引用”。 但我似乎无法使用子程序引用作为哈希“关键”。
在下面的示例代码,
- 我可以创建一个子程序($子参考)的引用,然后取消对它的引用运行子程序($子参考)
- 我可以很容易地使用该引用作为散列“值”,然后解除引用该
- 但我无法弄清楚如何使用引用作为哈希“关键”。 当我拔出钥匙散列,Perl的解释键作为一个字符串值(不是引用) -我现在明白 (!感谢这个网站的)。 所以,我已经试过哈希::多键,但似乎把它变成一个数组引用。 我希望把它当作一个子程序/码参考,假设这是某种可能吗?
任何其他的想法?
use strict;
#use diagnostics;
use Hash::MultiKey;
my $subref = \&hello;
#1:
&$subref('bob','sue'); #okay
#2:
my %hash;
$hash{'sayhi'}=$subref;
&{$hash{'sayhi'}}('bob','sue'); #okay
#3:
my %hash2;
tie %hash2, 'Hash::MultiKey';
$hash2{$subref}=1;
foreach my $key (keys %hash2) {
print "Ref type is: ". ref($key)."\n";
&{$key}('bob','sue'); # Not okay
}
sub hello {
my $name=shift;
my $name2=shift;
print "hello $name and $name2\n";
}
这是返回什么:
hello bob and sue
hello bob and sue
Ref type is: ARRAY
Not a CODE reference at d:\temp\test.pl line 21.
这是正确的,正常的哈希键只是一个字符串。 事情是不是琴弦强制为他们的字符串表示。
my $coderef = sub { my ($name, $name2) = @_; say "hello $name and $name2"; };
my %hash2 = ( $coderef => 1, );
print keys %hash2; # 'CODE(0x8d2280)'
领带 ING是惯用的手段来修改行为,但是哈希::多键不帮你,它有不同的用途:正如其名字,你可能有多个键,但也只简单的字符串:
use Hash::MultiKey qw();
tie my %hash2, 'Hash::MultiKey';
$hash2{ [$coderef] } = 1;
foreach my $key (keys %hash2) {
say 'Ref of the key is: ' . ref($key);
say 'Ref of the list elements produced by array-dereferencing the key are:';
say ref($_) for @{ $key }; # no output, i.e. simple strings
say 'List elements produced by array-dereferencing the key are:';
say $_ for @{ $key }; # 'CODE(0x8d27f0)'
}
相反,使用领带:: RefHash 。 (典批判:喜欢这种语法与->
。解引用一个CODEREF箭头)
use 5.010;
use strict;
use warnings FATAL => 'all';
use Tie::RefHash qw();
my $coderef = sub {
my ($name, $name2) = @_;
say "hello $name and $name2";
};
$coderef->(qw(bob sue));
my %hash = (sayhi => $coderef);
$hash{sayhi}->(qw(bob sue));
tie my %hash2, 'Tie::RefHash';
%hash2 = ($coderef => 1);
foreach my $key (keys %hash2) {
say 'Ref of the key is: ' . ref($key); # 'CODE'
$key->(qw(bob sue));
}
从perlfaq4 :
我如何使用引用作为哈希键?
(贡献的布莱恩d FOY和Ben莫罗)
哈希键是字符串,所以你不能真正使用参考的关键。 当您尝试这样做,perl的转动参考到它的字符串化的形式(例如,HASH(0xDEADBEEF))。 从那里,你不能回来从字符串化的形式引用,至少没有做你自己一些额外的工作。
请记住,在散列条目仍然会在那里,即使引用变量超出范围,这是完全有可能的Perl在同一地址随后分配一个不同的变量。 这将意味着一个新的变量可能会意外地与旧的价值相关联。
如果你有Perl 5.10或更高版本,而你只是想在以后对存储进行查找的参考值,可以使用核心哈希::的Util :: Fieldhash模块。 这也将重命名处理的按键,如果你使用多线程(这将导致在新地址重新分配所有的变量,改变他们的字串),和垃圾收集的条目时,引用变量超出范围。
如果你确实需要能够得到一个真正的参考,从每个哈希进入回来,你可以使用领带:: RefHash模块,它确实需要的为你工作。
所以它看起来像领带:: RefHash会做你想要什么。 但说实话,我不认为你需要做的是一个特别好的主意。
你为什么需要它? 比如,如果你需要存储的参数中的散列函数,你可以使用环比:
my %hash;
$hash{$subref} = { sub => $subref,
arg => [qw/bob sue/],
};
foreach my $key (keys %hash) {
print "$key: ref type is: " . ref($key) . "\n";
$hash{$key}{sub}->( @{ $hash{$key}{arg} } );
}
但是,你也许可以选择一个更好的钥匙呢。