【问题标题】:Getting wrong argument value when using @_ in Perl subroutine在 Perl 子例程中使用 @_ 时得到错误的参数值
【发布时间】:2013-03-11 07:06:45
【问题描述】:

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

谁能告诉我可能导致问题的原因?使用@_ 传递单个参数有什么限制吗?

谢谢!

【问题讨论】:

    标签: perl arguments subroutine


    【解决方案1】:

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

    从子例程的参数中获取局部变量的简单经验法则是始终在 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,用于收集传递的任何额外参数。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 欢迎来到 Stack Overflow。您的答案包含正确的核心信息,所以我给了您一个赞成票,但我认为如果您对您的意思进行更多解释,您会做得更好。问这个问题的人可能无法从你的回答中看出他们需要做什么来解决他们的问题(或者,因为他们已经确定my $def = $_[0]; 有效,为什么使用@_ 的版本不起作用)。这是最小答案和好的答案之间的区别。 (如果半票是一个选项,你可能只会得到我半票。)
      • 感谢您的意见肯定会改善我回答问题的方式。
      【解决方案3】:

      一切都与上下文有关。这是一个例子:

      @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
      

      【讨论】:

      • 那很好。如果你有几个my 关键字会更好。然后最好将解释应用于子程序的参数情况。
      • 感谢您的建议。我删除了那些 should be there my 声明以获得更好的信噪比,就像大多数 CPAN 模块示例一样。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-16
      • 2013-10-31
      • 2010-11-12
      • 2015-07-06
      • 1970-01-01
      • 2019-11-15
      相关资源
      最近更新 更多