我想将库从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)
或test([ @a ], $i)
。或者更好的方法是,先传递标量参数,然后将其余参数传递到数组中。我建议采用解决方案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
将允许子控件更改数组中的值,因此将其作为匿名数组传递会[ @a ]
更安全。
另外,代码:
my @a;
print ref(\@a);
将打印ARRAY
,但不ref(@a)
打印任何内容。
另外,如果你曾经使用过
use strict;
use warnings;
你会得到非常启发性的警告
Argument "ARRAY" isn't numeric in numeric eq (==)
哪个告诉你在字符串比较中,应该使用eq
而不是==
数字。因为Perl会0
在数值上下文中静默将空字符串转换为,并将字符串转换ARRAY
为0
,比较的结果为true,这会使你的比较返回假阳性。
不使用strict
和不编写Perl代码warnings
。
谢谢,很好的回答!
不客气