Perl:cmpthese文本vs传递参数的匿名子问题

时间:2010-11-15 20:50:42

标签: perl parameters eval subroutine

如果您在Perl Benchmark模块的文档中阅读了cmpthese,则说明cmpthesetimethese可以与文本或子例程引用中的代码一起使用。文档似乎暗示这些形式完全可以互换:

# Use Perl code in strings...
timethese($count, {
'Name1' => '...code1...',
'Name2' => '...code2...',
});
# ... or use subroutine references.
timethese($count, {
'Name1' => sub { ...code1... },
'Name2' => sub { ...code2... },
});

我在使用cmpthese的字符串形式与子例程引用表单传递参数时遇到了困难。 @array中的值未通过或我有运行时错误。

我有以下代码:

#!/usr/bin/perl
use strict; use warnings;
use Benchmark qw(:all);

my @array = qw( first second third );

sub target {
    my $str =  $_[0];
    print "str=$str\n";
}

sub control {
    print "control: array[0]=$array[0]\n";
}

my $sub_ref=\⌖
my $control_ref=\&control;

print "\n\n\n";

# ERROR: array does not get passed...
cmpthese(1, {
    'target text' => 'target(@array)',
    'control 1' => 'control()', 
});

# This is OK...
cmpthese(1, {
    'sub code ref' => sub { target(@array) },
    'control 2' => sub { control() },
});

# This is OK too...
cmpthese(1, {
    'target sub' => sub { $sub_ref->(@array) },
    'control 3' => sub { $control_ref->() },
});

# fixed paramenters work:
cmpthese(1, {
    'target text fixed' => 'target("one", "two", "three")',
    'control 4' => 'control()', 
});

# Run time error...
cmpthese(1, {
    'text code ref' => '$sub_ref->(@array)',
    'control 5' => '$control_ref->()',
});

我使用eval正确使用的所有表单,所以我认为这可能是Benchmark的一个问题?我已经使用了我所有的谷歌foo尝试找到两种形式之间的一些记录差异,但我不能。

有谁知道我上面的简单示例似乎没有按预期工作的原因?代码中的注释表明我在OS X上遇到的问题,Perl 5.10.0。

2 个答案:

答案 0 :(得分:6)

传递给cmpthesetimethese的文字被传播到基准内容深处的eval语句。除非文本中的参数是文字或全局变量,否则它们在评估时不会在范围内,并且会出现运行时错误。

使用参数的匿名子版本为您的参数提供词法闭包,一切都会很好。

答案 1 :(得分:5)

我没有仔细研究过这个问题,但我的猜测是当Benchmark将字符串转换为代码时,词汇变量@array不在范围内。如果您将@array变为our变量,那么事情可能会奏效。

但总的来说,我发现使用代码引用更容易。