【问题标题】:Modify subroutine parameter (Perl)修改子程序参数(Perl)
【发布时间】:2015-01-06 10:07:29
【问题描述】:

我想编写一个 Perl 子例程 first,它接受一个列表作为输入,返回列表中的第一个元素并从列表中删除第一个元素。

像这样:

@list = (1,2,3);
print first(@list); // 1
print @list; // 23

这不太行:

sub first(@) {
    return shift @_;
}

我得到的是:

print first(@list); // 1
print @list; // 123

堆栈变量@_ 改变了我期望的方式(首先是(1, 2, 3),然后是(2, 3)),但我作为输入提供的列表(@list)没有改变。我认为堆栈变量保存了对它所引用的变量的引用。

当我在子例程中更改列表元素时,它也会更改 @list 中的某些内容,但不是我想要的,而是那个 + 1。所以如果我在子例程中编写:

@_[0] = "X";

在执行子程序打印@list后,我会得到2X6

【问题讨论】:

  • 为什么不使用shift 来实现呢?
  • 这就是我在子程序中所做的
  • 但是为什么要编写子程序呢?什么时候可以简单地使用shift

标签: perl parameters subroutine


【解决方案1】:

你需要在@原型前面加上一个斜杠来得到一个数组引用,然后修改引用。如果您只使用@,您将在子程序中获得数组@list 的副本(因此不会修改父程序中的数组)。来自http://perldoc.perl.org/perlsub.html#Prototypes

无反斜线的原型字符具有特殊含义。任何 unbackslashed @ 或 % 吃掉所有剩余的参数,并强制列表 上下文。

所以你可以写:

use strict;
use warnings;

sub first (\@) {
    my $a = shift;
    return shift @$a;
}

my @list = (1,2,3);
print first(@list) . "\n"; 
print "@list" . "\n"; 

输出:

1
2 3

【讨论】:

    【解决方案2】:

    你没有列表,你有数组。 Perl 中的数组和列表是不同的(正如great blog post 解释的那样)。如果您有一个名为 @list 的数组,那么您肯定会迷惑自己(以及将来维护您代码的人)。

    【讨论】:

      猜你喜欢
      • 2014-12-12
      • 1970-01-01
      • 2016-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多