如何使用'子程序引用'作为散列键 [英] How to use a 'subroutine reference' as a hash key

查看:146
本文介绍了如何使用'子程序引用'作为散列键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Perl中,我正在学习如何取消引用子程序引用。但我似乎无法使用子例程引用作为散列键。



在以下示例代码中,


  1. 我可以创建对子例程($ subref)的引用,然后对其进行解引用以运行子例程(& $ subref)

  2. 我可以使用引用作为哈希'值',然后轻松取消引用

  3. 但我无法弄清楚如何将引用用作哈希'键'。当我将密钥从散列中取出时,Perl将该密钥解释为一个字符串值(而不是引用) - 我现在了解一个>(感谢这个网站!)。所以我试过Hash :: MultiKey,但是这似乎把它变成一个数组引用。我想把它当作一个子程序/代码引用,假设这是可能的?

其他想法?

  use strict; 
#use diagnostics;
使用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%ha​​sh2,'Hash :: MultiKey';
$ hash2 {$ subref} = 1;
foreach我的$ key(键%hash2){
printRef type is:。 REF($键) \\\

& {$ key}('bob','sue'); #不好
}

你好{
我$ $ =移动;
my $ name2 = shift;
打印hello $ name and $ name2\\\
;
}

这是返回的内容:

  hello bob和sue 
hello bob和sue
引用类型是:ARRAY
不是d:\temp\\处的代码引用\\ test.pl第21行。


一个正常的散列键只是一个字符串。

  my $ coderef = sub {my($ name,$ name2) = @_;说你好$ name和$ name2; }; 
my%hash2 =($ coderef => 1,);
打印键%hash2; #'CODE(0x8d2280)'

绑定是修改该行为的常用方法,但哈希值: :MultiKey 不会帮助你,它有一个不同的目的:正如名字所说,你可能有多个键,但只有简单的字符串:

 使用Hash :: MultiKey qw(); 
绑定我的%hash2,'Hash :: MultiKey';
$ hash2 {[$ coderef]} = 1;
foreach我的$ key(键%hash2){
说'引用的关键是:'。 REF($键);
表示'由数组引用的列表元素的引用 - 解引用关键字是:';
表示@ {$ key}的ref($ _); #没有输出,即简单的字符串
说'列表元素通过数组解引用键生成:';
表示$ _表示@ {$ key}; #'CODE(0x8d27f0)'
}

改为使用 Tie :: RefHash 。 (代码批评:优先使用 - > >箭头来取消引用coderef。)

 使用5.010; 
使用strict;
使用警告FATAL => '所有';
使用Tie :: RefHash qw();

my $ coderef = sub {
my($ name,$ name2)= @_;
表示hello $ name和$ name2;
};

$ coderef->(qw(bob sue));

my%hash =(sayhi => $ coderef);
$ hash {sayhi} - >(qw(bob sue));

绑定我的%hash2,'Tie :: RefHash';
%hash2 =($ coderef => 1);
foreach我的$ key(键%hash2){
说'引用的关键是:'。 REF($键); #'CODE'
$ key->(qw(bob sue));
}


In Perl, I'm learning how to dereference 'subroutine references'. But I can't seem to use a subroutine reference as a hash 'key'.

In the following sample code,

  1. I can create a reference to a subroutine ($subref) and then dereference it to run the subroutine (&$subref)
  2. I can use the reference as a hash 'value' and then easily dereference that
  3. But I cannot figure out how to use the reference as a hash 'key'. When I pull the key out of the hash, Perl interprets the key as a string value (not a reference) - which I now understand (thanks to this site!). So I've tried Hash::MultiKey, but that seems to turn it into an array reference. I want to treat it as a subroutine/code reference, assuming this is somehow possible?

Any other ideas?

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";
}

This is what is returned:

hello bob and sue
hello bob and sue
Ref type is: ARRAY
Not a CODE reference at d:\temp\test.pl line 21.

解决方案

That is correct, a normal hash key is only a string. Things that are not strings get coerced to their string representation.

my $coderef = sub { my ($name, $name2) = @_; say "hello $name and $name2"; };
my %hash2 = ( $coderef => 1, );
print keys %hash2;  # 'CODE(0x8d2280)'

Tieing is the usual means to modify that behaviour, but Hash::MultiKey does not help you, it has a different purpose: as the name says, you may have multiple keys, but again only simple strings:

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)'
}

Instead, use Tie::RefHash. (Code critique: prefer this syntax with the -> arrow for dereferencing a 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));
}

这篇关于如何使用'子程序引用'作为散列键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆