首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用“子例程引用”作为散列键

如何使用“子例程引用”作为散列键
EN

Stack Overflow用户
提问于 2012-05-29 08:13:36
回答 3查看 1.4K关注 0票数 2

在Perl中,我正在学习如何取消“子例程引用”。但我似乎不能使用子例程引用作为散列“键”。

在下面的示例代码中,

  1. 我可以创建一个对子例程($subref)的引用,然后取消引用来运行子例程(&$subref)
  2. 我可以使用引用作为散列‘值’,然后很容易取消引用
  3. 但我不知道如何将引用用作散列“键”。当我从哈希中取出键时,Perl将键解释为字符串值(而不是引用)--我现在使用理清 (感谢这个站点!)。因此,我尝试过Hash::MultiKey,但这似乎将其转换为数组引用。我想把它当作子例程/代码引用,假设这是可能的?

还有其他想法吗?

代码语言:javascript
复制
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";
}

这是返回的内容:

代码语言:javascript
复制
hello bob and sue
hello bob and sue
Ref type is: ARRAY
Not a CODE reference at d:\temp\test.pl line 21.
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-29 09:02:35

这是正确的,一个普通的散列键只是一个字符串。不是字符串的东西会被迫使用它们的字符串表示形式。

代码语言:javascript
复制
my $coderef = sub { my ($name, $name2) = @_; say "hello $name and $name2"; };
my %hash2 = ( $coderef => 1, );
print keys %hash2;  # 'CODE(0x8d2280)'

领带ing是修改该行为的常用方法,但是散列::多键对您没有帮助,它有一个不同的目的:正如名称所述,您可能有多个键,但同样只有简单的字符串:

代码语言:javascript
复制
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。(代码评论:更喜欢使用->箭头的语法来取消引用代码。)

代码语言:javascript
复制
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));
}
票数 2
EN

Stack Overflow用户

发布于 2012-05-29 08:39:43

来自perlfaq4

如何使用引用作为哈希键? (由brian d foy和Ben Morrow提供) 散列键是字符串,因此不能真正使用引用作为键。当您尝试这样做时,perl将引用转换为它的字符串化形式(例如,散列(0xDEADBEEF ) )。在那里,您无法从字符串形式中获得引用,至少不需要自己做一些额外的工作。 请记住,即使引用的变量超出了作用域,散列中的条目仍然存在,Perl完全有可能随后在同一个地址分配一个不同的变量。这意味着一个新变量可能意外地与一个旧变量的值相关联。 如果您有Perl 5.10或更高版本,并且只想在引用中存储一个值,以便稍后查找,则可以使用核心哈希::Util::Field散列模块。如果您使用多个线程(这会导致在新地址重新分配所有变量,更改它们的字符串化)和垃圾--当引用的变量超出作用域时,这也将处理重命名键。 如果您实际上需要能够从每个散列条目获得一个真正的引用,您可以使用Tie::RefHash模块,它为您完成所需的工作。

所以看起来领带::RefHash会做你想做的事。但老实说,我不认为你想做的是一个特别好的主意。

票数 1
EN

Stack Overflow用户

发布于 2012-05-29 08:38:47

你为什么需要它?例如,如果需要将参数存储到散列中的函数,则可以使用HoH:

代码语言:javascript
复制
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} } );
}

但是,无论如何,你都可以选择一个更好的钥匙。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10795386

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档