此问题与 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,所以我现在看看它们。事实证明,它们并不像我想象的那么复杂。
答案 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
以外的任何内容使用名为b
或sort
的变量通常不是一个好主意。)
答案 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