如果我能以shift、push和其他内置子例程的工作方式使用子例程,那么我的脚本中的很多事情都会变得更容易:它们都可以直接更改传递给它的变量,而不需要返回更改。
当我尝试这样做时,变量会在某个时刻被复制,而我似乎只是简单地更改了副本。我知道这对于引用来说是很好的,但它甚至会发生在数组和散列中,我觉得我只是把我正在处理的变量传递给sub,这样就可以在它上面做更多的工作:
@it = (10,11);
changeThis(@it);
print join(" ", @it),"\n"; #prints 10 11 but not 12
sub changeThis{
$_[2] = 12;
}
有没有办法做到这一点?我知道这不是最佳实践,但在我的情况下,这将是非常方便的。
发布于 2011-06-20 13:19:39
问题是sub调用将变量扩展为一个值列表,该列表被传递给sub例程。即传递一个副本,而不是变量本身。您的子调用等于:
changeThis(11, 12);
如果您希望更改原始数组,请改为传递一个引用:
use strict;
use warnings;
my @it = (10,11);
changeThis(\@it);
print join(" ", @it),"\n";
sub changeThis{
my $array = shift;
$$array[2] = 12;
}
此外,@_[2]
还会给出以下警告:
Scalar value @_[2] better written as $_[2]
如果你使用use warnings
,你当然应该这么做。除非您确切地知道自己在做什么,否则没有充分的理由不启用警告和严格。
发布于 2011-06-20 13:33:22
这就是原型的用途:
#!/usr/bin/perl
use strict;
use warnings;
sub changeThis(\@); # the argument will be seen as an array ref (prototype must come before the call!)
my @it = (10,11);
changeThis @it; # even when called with an array
print join(" ", @it),"\n"; #prints 10 11 12
sub changeThis(\@)
{ my( $ar)= @_; $ar->[2]= 12; }
有关详细信息,请参阅http://perldoc.perl.org/perlsub.html#Prototypes。
不过,这并不是一个真正流行的方法,传递实际的数组引用可能是一个更好的替代方法,涉及的魔力更少。
发布于 2011-06-20 13:36:33
正如前面的答案所建议的,您应该使用传递给子例程的引用。此外,如果要通过documentation for Prototypes进行读取,还可以使用隐式引用
sub changeThis(\@);
@it = (10,11);
changeThis @it;
print join(" ", @it),"\n"; #prints 10 11 12
sub changeThis(\@){
$_[0][2] = 12;
}
(请注意,您必须在第一次调用之前预先声明您的subs,或者将子定义放在顶部。)
https://stackoverflow.com/questions/6411668
复制