1

有没有办法告诉/强制 perl 编译器在循环中缓存值?

当然我可以在循环之外创建我的值,但是随着代码复杂性的增加,我发现在循环内部创建值更具可读性,尽管它们不会改变

例如:

my $key = shift;
my @input = @_;
my %output;
foreach(@input) {
    my $output_tmp = specialOperation($_);
    ...
    my $key_tmp = constantOperation($key);
    my $specialKey = specialOperation2($_,$key_tmp);
    ...
    $output{$specialKey} = $tmp;
}

$keyTmp在每次迭代中都有相同的值,我希望编译器缓存它

在正则表达式中,您可以使用o-flag
是否有类似的东西(例如关键字)来完成此操作?

4

2 回答 2

4

通过如下更改代码实际上并没有引入任何额外的复杂性:

my $key_tmp = constantOperation($key);
my %output
foreach ( @input ) {
    my $output_tmp = special_operation($_);
    my $specialKey = specialOperation2($_,$key_tmp);
    $output{$specialKey} = $tmp;
}

但是暂时接受你有一个合理的未公开论据来解释你为什么不想这样做,另一种可能性(如果 constantOperation 是一个纯函数)是使用 Memoize。

use Memoize;
memoize 'constantOperation';

my $key = shift;
my @input = @_;
my %output;
foreach( @input ) {
    my $output_tmp = special_operation;
    my $key_tmp = constantOperation($key);
    my $specialKey = specialOperation2($_,$key_tmp);
    $output{$specialKey} = $tmp;
}

后者并不能避免重复的函数调用,但确实会在名为 constantOperation 的函数内引起缓存,因此使用先前使用的参数的后续调用将提供缓存的结果。

回到第一个示例,您可以将“my”声明移出循环,然后在循环中使用如下内容 $key_tmp //= constantOperation($key);:这可能是这样的:

my $key = shift;
my @input = @_;
my %output;
my $key_tmp;
foreach( @input ) {
    my $output_tmp = special_operation;
    $key_tmp //= constantOperation($key);
    my $specialKey = specialOperation2($_,$key_tmp);
    $output{$specialKey} = $tmp;
}

而这就是 Perl,总有另一种方法可以做到这一点。启用“状态”功能,然后更改my $key_tmpstate $key_tmp. 这可能是这样的:

use feature 'state';
my $key = shift;
my @input = @_;
my %output;
foreach( @input ) {
    my $output_tmp = special_operation;
    state $key_tmp = constantOperation($key);
    my $specialKey = specialOperation2($_,$key_tmp);
    $output{$specialKey} = $tmp;
}
于 2012-08-13T09:41:24.427 回答
0

在循环外声明$key_tmp,然后在循环内检查它是否已经被分配,然后再重新计算:

my ($key, @input) = @_;
my %output;
my $key_tmp;

foreach(@input) {
    my $output_tmp = specialOperation($_);
    ...
    $key_tmp = constantOperation($key) unless $key_tmp;
    my $specialKey = specialOperation2($_,$key_tmp);
    ...
    $output{$specialKey} = $tmp;
}
于 2012-08-13T10:26:25.853 回答