3

我在使用 @_ 将单个参数传递给 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];

谁能告诉可能导致问题的原因?使用 @_ 传递单个参数是否有任何限制?

谢谢!

4

3 回答 3

13

你得到了正确的行为,尽管它不是你所期望的。

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

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

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

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

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

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

于 2013-03-11T07:12:40.560 回答
1

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

于 2013-03-11T07:15:35.740 回答
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
于 2013-03-11T07:25:01.023 回答