自动调用作为子程序引用的哈希值 [英] Automatically call hash values that are subroutine references

查看:97
本文介绍了自动调用作为子程序引用的哈希值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个散列,其中的几个值不是标量数据,而是返回标量数据的匿名子例程。我想使这个完全透明的部分代码查找哈希值,所以它不必知道一些哈希值可能是匿名子程序,返回标量数据,而不是纯粹的旧标量数据。



为此,有没有办法在访问密钥时执行匿名子程序,而不使用任何特殊语法?这是一个简化的例子,说明了目标和问题:

 #!/ usr / bin / perl 

my%hash =(
key1 =>value1,
key2 => sub {
returnvalue2;#在实际代码中,该值可以不同
},
);

foreach我的$ key(排序键%hash){
print $ hash {$ key}。 \\\
;
}

我想要的输出是:

  perl ./test.pl 
value1
value2

相反,这是我得到的:

  perl ./test.pl 
value1
CODE(0x7fb30282cfe0)


解决方案

有一个名为魔术的功能,允许在访问变量时调用代码。



向变量添加魔法可大大减慢对该变量的访问速度,但有些更多




  • 没有必要访问哈希神奇的每个元素,只是一些值。

  • tie 是一种更昂贵的魔法形式,这里不需要。



因此,最有效的解决方案如下:

  use Time :: HiRes qw(time) ; 
使用Variable :: Magic qw(cast wizard);

{
my $ wiz = wizard(
data => sub {my $ code = $ _ [1]; $ code},
get => ; sub {$ {$ _ [0]} = $ _ [1] - >();},
);

sub make_evaluator {cast($ _ [0],$ wiz,$ _ [1])}
}

我的%
$ hash {key1} ='value1';
make_evaluator($ hash {key2},sub {'value2@'.time});

print($ hash {$ _} \\\
)for qw(key1 key2 key2);

输出:

 code> value1 
value2@1462548850.76715
value2@1462548850.76721






其他示例:

 我的%hash; make_evaluator($ hash {key},sub {...}); 
我的$哈希; make_evaluator($ hash-> {$ key},sub {...});

我的$ x; make_evaluator($ x,sub {...});
make_evaluator(my $ x,sub {...});

make_evaluator(...,sub {...});
make_evaluator(...,\& some_sub);

您还可以修复现有的哈希。在哈希哈希方案中,

 我的$ hoh = {
{
key1 => ; 'value1',
key2 => sub {...},
...
},
...
);

为$ h(值(%$ hoh)){
为$ v(值(%$ h)){
if(ref($ v)eq 'CODE'){
make_evaluator($ v,$ v);
}
}
}


I have a hash with a few values that are not scalar data but rather anonymous subroutines that return scalar data. I want to make this completely transparent to the part of the code that looks up values in the hash, so that it doesn't have to be aware that some of the hash values may be anonymous subroutines that return scalar data rather than just plain old scalar data.

To that effect, is there any way to have the anonymous subroutines executed when their keys are accessed, without using any special syntax? Here's a simplified example that illustrates the goal and the problem:

#!/usr/bin/perl

my %hash = (
    key1 => "value1",
    key2 => sub {
        return "value2"; # In the real code, this value can differ
    },
);

foreach my $key (sort keys %hash) {
    print $hash{$key} . "\n";
}

The output I would like is:

perl ./test.pl
value1
value2

Instead, this is what I get:

perl ./test.pl
value1
CODE(0x7fb30282cfe0)

解决方案

There's a feature called "magic" that allows code to be called when variables are accessed.

Adding magic to a variable greatly slows down access to that variable, but some are more expensive than others.

  • There's no need to make access to every element of the hash magical, just some values.
  • tie is an more expensive form of magic, and it's not needed here.

As such, the most efficient solution is the following:

use Time::HiRes     qw( time );
use Variable::Magic qw( cast wizard );

{
   my $wiz = wizard(
      data => sub { my $code = $_[1]; $code },
      get => sub { ${ $_[0] } = $_[1]->(); },
   );

   sub make_evaluator { cast($_[0], $wiz, $_[1]) }
}

my %hash;
$hash{key1} = 'value1';
make_evaluator($hash{key2}, sub { 'value2@'.time });

print("$hash{$_}\n") for qw( key1 key2 key2 );

Output:

value1
value2@1462548850.76715
value2@1462548850.76721


Other examples:

my %hash; make_evaluator($hash{key}, sub { ... });
my $hash; make_evaluator($hash->{$key}, sub { ... });

my $x; make_evaluator($x, sub { ... });
make_evaluator(my $x, sub { ... });

make_evaluator(..., sub { ... });
make_evaluator(..., \&some_sub);

You can also "fix up" an existing hash. In your hash-of-hashes scenario,

my $hoh = {
   { 
      key1 => 'value1',
      key2 => sub { ... },
      ...
   },
   ...
);

for my $h (values(%$hoh)) {
   for my $v (values(%$h)) {
      if (ref($v) eq 'CODE') {
         make_evaluator($v, $v);
      }
   }
}

这篇关于自动调用作为子程序引用的哈希值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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