如何在引用参数上使用local *?

时间:2011-11-07 06:55:19

标签: perl scope

此问题与 Effective Perl Programming 中第46项的最后一点有关。

我测试了这个函数,它允许你传递数组引用,但是将它们作为本地数组访问:

use strict;
sub max_v_local {
    local ( *a, *b ) = @_;
    my $n = @a > @b ? @a : @b;
    my @result;
    for ( my $i = 0 ; $i < $n ; $i++ ) {
        push @result, $a[$i] > $b[$i] ? $a[$i] : $b[$i];
    }
    @result;
}

但除非我不使用strict

,否则会出现以下错误
Variable "@a" is not imported
Variable "@b" is not imported
Global symbol "@a" requires explicit package name
Global symbol "@b" requires explicit package name

有没有办法用strict执行此操作?

更新

进一步的背景。以上子程序是对以下内容的改进。子例程需要2个arrayrefs,但在子例程中使用arrayrefs会变得混乱。上面的代码可能更快,更具可读性,因为它使您能够将arrayrefs作为本地数组访问。

sub max_v {
    my ( $a, $b ) = @_;
    my $n = @$a > @$b ? @$a : @$b; # no. of items
    my @result;
    for ( my $i = 0 ; $i < $n ; $i++ ) {
        push @result, $$a[$i] > $$b[$i] ? $$a[$i] : $$b[$i];
    }
    @result;
}

在此之前,我没有太多关注globs,所以我现在看看它们。事实证明,它们并不像我想象的那么复杂。

4 个答案:

答案 0 :(得分:3)

是。用our声明它们:

use strict;
sub max_v_local {
    local ( *x, *y ) = @_;
    our (@x, @y);
    my $n = @x > @y ? @x : @y;
    my @result;
    for ( my $i = 0 ; $i < $n ; $i++ ) {
        push @result, $x[$i] > $y[$i] ? $x[$i] : $y[$i];
    }
    @result;
}

(对a以外的任何内容使用名为bsort的变量通常不是一个好主意。)

答案 1 :(得分:3)

正如cjm所提到的,你需要用our声明变量(或者使用完全限定的名字)。

现在提供一些提示。首先,从@_分配到未经检查的glob是一种赌博。我会写这样的一行:

our (@a, @b);
local (*a, *b) = map \@$_ => @_;

这样,您确保传递给子例程的唯一内容实际上是数组引用。如果值不是数组引用,Perl将抛出错误。如果你想要更详细的信息,你当然可以写一份详细的检查:

ref eq 'ARRAY' or die "..." for @_;
our (@a, @b);
local (*a, *b) = @_;

答案 2 :(得分:1)

您想要使用包变量@a@b,因此您要使用our。它几乎是一个变量no strict "vars";,它是词汇范围的。

sub max_v_local {
    local ( *a, *b ) = @_;
    our ( @a, @b );
    ...
}

但是你的算法存在问题。您将较长数组的元素与不存在的元素进行比较。这将给出警告并给出负值的错误结果。修正:

sub max_v_local {
    local ( *a, *b ) = @_;
    our ( @a, @b );
    my $n = @a < @b ? @a : @b;
    return
       ( map { $a[$_] > $b[$_] ? $a[$_] : $b[$_] } 0..$n-1 ),
       @a[ @b .. $#a ],
       @b[ @a .. $#b ];
}

此外,引用并返回列表很奇怪。您可能想要返回数组引用。 (return [ ... ];

答案 3 :(得分:0)

认为可能是因为您没有明确声明您的变量@a和@b