正确检测Perl子程序参数是否为数组
我正在尝试将库从 Javascript 移植到 Perl,但是在检测数组参数时遇到了一些问题。
一个精简的示例(在 Javascript 中)如下所示:
const say = console.log;
function test(array, integer)
{
if(Array.isArray(array))
{
say("First argument is array");
}
else
{
say("First argument is not array");
array = [array];
}
for(let index = 0; index < array.length; ++index)
{
say(array[index]);
}
say("Second argument: ", integer);
say("");
}
var a = ["foo", "bar"];
var t = "baz";
var i = 1024;
say("Testing on array");
test(a, i);
say("Testing on string");
test(t, i);
输出:
Testing on array
First argument is array
foo
bar
Second argument: 1024
Testing on string
First argument is not array
baz
Second argument: 1024
这是 Perl 版本:
use feature qw(say);
sub test
{
my ($text, $integer ) = @_;
my (@array) = @_;
if(ref(@array) == "ARRAY")
{
say("First argument is array");
}
else
{
say("First argument is not array");
@array = ($text);
}
for my $index (0 .. $#array)
{
say($array[$index]);
}
say("Second argument: ", $integer);
}
my @a = ("foo", "bar");
my $t = "baz";
my $i = 1024;
say("Testing on array");
test(@a, $i);
say("Testing on string");
test($t, $i);
输出:
Testing on array
First argument is array
foo
bar
1024
Second argument: bar
Testing on string
First argument is array
baz
1024
Second argument: 1024
我还尝试了许多其他方法,例如在数组名称前加上反斜杠等等,但都无济于事。我相当肯定这在 Perl 中一定是可能的。或者这可能是语言本身的某种限制?
回答
Perl 子程序不接受数组作为参数,只接受标量。子调用中的数组被折叠成一个标量列表。如果要传递数组,您有 2 个选项。
- 传递一个数组引用,例如
test(@a, $i), ortest([ @a ], $i)。或者更好的是,首先传递标量参数,然后将其余参数放入一个数组中。 - 深入研究 Perl 原型并了解它们的工作原理。
我建议解决方案 1。通常你可以做类似的事情
test($i, @a);
sub test {
my $i = shift;
my @a = @_;
....
}
或者
test($i, [ @a ]);
sub test {
my $i = shift;
my $aref = shift;
my @a = @$aref; # expand to normal array (not strictly needed)
....
}
请注意,将引用传递给数组@a将允许 sub 更改数组中的值,因此将其作为匿名数组传递[ @a ]更安全。
另外,代码:
my @a;
print ref(@a);
将打印ARRAY,但ref(@a)不会打印任何内容。
另外,如果你曾经使用过
use strict;
use warnings;
你会得到非常有启发性的警告
Argument "ARRAY" isn't numeric in numeric eq (==)
这告诉您在字符串比较中,您应该使用eq而不是==which 是数字。因为 Perl 会0在数字上下文中默默地将空字符串转换为 ,并将字符串转换ARRAY为0,所以比较的结果为真,这导致您的比较返回误报。
永远不要在没有strict和的情况下编写 Perl 代码warnings。