自动调用作为子程序引用的哈希值 [英] Automatically call hash values that are subroutine references
问题描述
我有一个散列,其中有几个值不是标量数据,而是返回标量数据的匿名子例程.我想让这对在散列中查找值的代码部分完全透明,以便它不必知道某些散列值可能是返回标量数据的匿名子例程,而不仅仅是普通的旧例程标量数据.
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";
}
我想要的输出是:
perl ./test.pl
value1
value2
相反,这就是我得到的:
Instead, this is what I get:
perl ./test.pl
value1
CODE(0x7fb30282cfe0)
推荐答案
有一个名为magic"的功能,允许在访问变量时调用代码.
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.
- 无需访问哈希的每个元素,只需访问一些值即可.
tie
是一种更昂贵的魔法形式,这里不需要它.
- 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 );
输出:
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屋!