Perl子例程参数列表 - “通过别名传递”?

7

我不敢相信这个序列:

my $line;
$rc = getline($line); # read next line and store in $line

我一直以为Perl参数是按值传递的,因此每当我需要传递一个大结构或传递一个要更新的变量时,我都会传递引用。
然而,在阅读perldoc中的细节后,我了解到@_由在参数列表中提到的变量的别名组成。在读取下一段数据后,getline()使用$_[0] = $data;将其返回,这将$data直接存储到$line中。
我喜欢这种方式-就像在C++中按引用传递。但是,我没有找到一种方法来为$_[0]分配更有意义的名称。有吗?

是的,Perl 总是按引用传递。 - newacct
好的 - 不要与Perl引用混淆,它们更像C指针,必须明确地取消引用。 - Chap
$arg = shift; $arg = $data; 这样做可以吗?还是说 'shift' 会复制参数呢?编辑:我测试了传递的标量和 'shift' 的参数地址,结果表明 'shift' 确实会复制,因此像上面那样分配给 $arg 不会按预期影响 $line。 :( - Sundar R
3个回答

7
你可以这样做,但不太美观:
use strict;
use warnings;

sub inc {
  # manipulate the local symbol table 
  # to refer to the alias by $name
  our $name; local *name = \$_[0];

  # $name is an alias to first argument
  $name++;
}

my $x = 1;
inc($x);
print $x; # 2

1
Data::Alias提供了相当多的美化功能。 - darch
此外,Method::Signatures拥有一个别名特性 - Joel Berger

0
一种允许多个不同参数的@Steve代码版本:
sub my_sub {
  SUB:
  for my $thisarg ( $_[0] ) {
    for my $thatarg ($_[1]) {
      code here sees $thisarg and $thatarg as aliases 
      last SUB;
    }
  }
}

当然,这会带来多级嵌套和自身的代码可读性问题,因此只在绝对必要时使用它。


0

最简单的方法可能就是使用循环,因为循环将其参数别名化为一个名称;即

sub my_sub {
  for my $arg ( $_[0] ) {
    code here sees $arg as an alias for $_[0]
  }
}

确实是对的,但不是我想要的——最好能为每个参数指定不同的名称。看起来Joel的代码做到了这一点,但正如他所说,这样做会非常混乱。 - Chap
@Chap:我已经添加了一个答案https://dev59.com/TXLYa4cB1Zd3GeqPZ50r#17343595,它允许为每个参数使用不同的名称,但这也有其自身的混乱之处。 - Sundar R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接