如何在Perl子程序中使用$a和$b



我想在我的匿名二进制函数中使用$a$b变量,就像在sort {$a <=> $b} (1, 2, 3)中完成一样,但我无法弄清楚为什么像

这样的代码
#!/usr/bin/env perl
use strict;
use warnings;
Foo::Bar(sub { $a + $b });
package Foo;
sub Bar {
    my ($function) = @_; 
    for my $i (1, 2, 3) {
        local ($a, $b) = ($i, $i);
        print $function->() . "n";
    }
}    

不起作用。而

#!/usr/bin/env perl
use strict;
use warnings;
Foo::Bar(sub { $_ });
package Foo;
sub Bar {
    my ($function) = @_; 
    for my $i (1, 2, 3) {
        local $_ = $i;
        print $function->() . "n";
    }
}

工作好。

我做错了什么?

$a$b是特殊的包变量。您从main包中调用Foo::Bar,因此需要设置$main::a$main::b才能使其工作。您可以使用caller来获取调用包的名称。这应该可以工作:

#!/usr/bin/env perl
use strict;
use warnings;
Foo::Bar(sub { $a + $b });
package Foo;
sub Bar {
    my ($function) = @_; 
    my $pkg = caller;
    for my $i (1, 2, 3) {
        no strict 'refs';
        local *{ $pkg . '::a' } = $i;
        local *{ $pkg . '::b' } = $i;
        print $function->() . "n";
    }
}    

以防有人感兴趣,从List::MoreUtils::PP v.0.428(截至2017年12月)复制粘贴:

# begin copyrighted content
sub reduce_u(&@)
{
    my $code = shift;
    # Localise $a, $b
    my ($caller_a, $caller_b) = do
    {
        my $pkg = caller();
        no strict 'refs';
        *{$pkg . '::a'}, *{$pkg . '::b'};
    };
    local (*$caller_a, *$caller_b);
    *$caller_a = ();
    for (0 .. $#_)
    {
        *$caller_b = $_[$_];
        *$caller_a = ($code->());
    }
    ${*$caller_a};
}
# end copyrighted content

仅在受no strict 'refs';影响的区域与上面的样本不同。如果没有严格的要求,可能是做不到的。

相关内容

  • 没有找到相关文章

最新更新