在Perl子例程中使用@_时获取错误的参数值

时间:2013-03-11 07:06:46

标签: perl arguments subroutine

使用@_将单个参数传递给Perl子例程时遇到了一个奇怪的错误。传入子程序的值在进入子程序后立即更改。

代码示例:

my $my_def = 0;
print "my_def = $my_def \n";
@someResult = doSomething($my_def);

sub doSomething {
    my $def = @_;
    print "def = $def \n";
    ...
}

这返回:

> my_def = 0
> def = 1  # instead of "0"

另一个奇怪的事情是代码在几个月前就已正常工作。

当我将其更改为:

时,问题得以解决
sub doSomething {
    my $def = $_[0];

有人能说出可能导致问题的原因吗?使用@_传递单个参数是否有任何限制?

谢谢!

3 个答案:

答案 0 :(得分:13)

你得到了正确的行为,虽然这不符合你的预期。

从子例程中的参数获取局部变量的简单经验法则是始终在my (...)声明中的变量列表周围使用括号:

sub do_something
{
    my ($def) = @_;
    ...
}

区别在于列表上下文和标量上下文。在标量上下文中,所有数组都返回数组中的元素数:在您的情况下为1。当你写my $def = @_时,你提供了标量上下文。当您使用my $def = $_[0]时,您显式访问了数组的元素零,这是一个标量(因此$ sigil),所以它再次起作用。

在一般情况下,您可能有:

sub do_something_else
{
    my ($arg1, $arg2, $arg3, @the_rest) = @_;
    ...
}

现在你有三个标量局部变量$arg1$arg2$arg3,以及一个数组@the_rest,它收集传递的任何额外参数。

答案 1 :(得分:1)

当分配给标量值的数组返回数组中的元素数时,答案很简单

答案 2 :(得分:1)

这完全取决于背景。这是一个例子:

@data = (0, 1, 2);

$count = @data;        # imply in scalar context
### $count: 3

$count = scalar @data; # same as above, but force scalar context
### $count: 3

$first = $data[0];     # both sides are in scalar context
### $first: 0

($first) = @data;      # both sides are in list context   
### $first: 0

$first = shift @data;  # get the first, but @data was modified
### $first: 0
### @data: (1, 2)

($second, $third) = @data;
### $second: 1
### $third: 2