2012-01-05 139 views
1

假设我们有一个子程序返回参考参考参数

sub aspirin { 
    my @items = qw(some items in here); 
    return \@items; 
} 

而另一子程序取一个数组引用

sub beetroot (\@) { 
    my $lst = shift; 
    print "$_\n" for @$lst; 
} 

我想从aspirin获取数组和饲料beetroot与它。我想这样做(的做法一个

my $L = aspirin; 
beetroot $L; 

但解释抱怨,我需要做以下代替(方法):

my $L = aspirin; 
beetroot @$L; 

所以我的问题是:

  • 为什么不是方法A能正常工作?该参数实际上是一个Array引用,这是我们想要的;
  • 是否需要复制整个列表内容而不进行赋值的解引用(如方法B中的那个)? (我猜不是,因为没有明确的副本)。

谢谢您的回答

+0

这是“为什么99%的原因不需要原型的原因列表”中的第一项。 – 2012-01-05 13:43:42

回答

1

存在Perl原型来修改解析器的行为,这很少需要。这也不例外。

如果“beetroot”没有任何其他参数,那么您应该使用@_而不是数组引用。

sub aspirin { 
    my @items = qw'some items in here'; 
    return @items if wantarray; # return a list in list context 
    return \@items; 
} 

sub beetroot { 
    print "$_\n" for @_; 
} 

my $L = aspirin; 
beetroot @$L; 

# the follow examples require the version of aspirin from this answer 

my @L = aspirin; 
beetroot @L; 

beetroot aspirin; # aspirin called in list context 

这将带来额外的好处,即如果您只想输入元素列表,则无需解析解析器。

这适用于新版本,但不适用于问题中的版本。

beetroot qw'some items in here'; 
beetroot aspirin; # aspirin called in list context 

为了使它与问题中的问题一起工作,您必须创建一个匿名数组。有趣的是,这也适用于这个答案中的版本。

beetroot @{ [qw'some items in here'] }; 
# the follow examples use the version of aspirin from this answer 
beetroot @{ [aspirin] }; 
beetroot @{ scalar aspirin }; 
beetroot @{ aspirin }; 

如果你真的想 “beetroot” 与数组引用工作。 我会这样写。

sub beetroot{ 
    my($lst) = @_; # similar to my $lst = shift 
    print "$_\n" for @$lst; 
} 

my $L = aspirin; 
beetroot $L; 

my @L = aspirin; # using the aspirin from this answer 
beetroot \@L; 

beetroot [qw'some items in here']; 
# the follow examples use the version of aspirin from this answer 
beetroot scalar aspirin; # force aspirin to return an array reference 
beetroot [ aspirin ]; # copy the array 

这样,如果你想使用引用减少的Perl的内存占用,或者你有其他投入“beetroot”我只会写。

6

原型\@并不意味着数组引用。这意味着给我一个数组,但我会得到它的一个引用作为参数(见perldoc perlsub

报价:

任何反斜杠的原型人物代表实际的论点,即 绝对必须以该字符开始如部分的@_ 将是在 子程序调用中给出的实际参数的引用传递的值,通过施加到"\"该参数获得。

或换句话说,不要使用原型,除非你真的知道他们在做什么。

+0

关于'perldoc perlsub'我可以这样理解:“这个特性的目的主要是让你定义像内置函数一样工作的子程序。正如我所能理解的(纠正我,如果我错了),内置函数与普通函数不同,它们可能有副作用,所以我应该只在我的数组上使用'\ @'时才使用'\ @'参数。它是否正确? – Dacav 2012-01-05 13:25:03

+0

不正确;正常功能也可能有副作用。相反,请考虑如何重新执行调用'push @ a,@ b'。如果你调用'my_push @ a,@ b',你的函数将会收到一个名为'@ _'的数组,无法知道'@ a'结束和'@ b'开始的位置。要解决这个问题,你可以使用引用('my_push \ @a,\ @ b'或'my_push \ @ a,@ b')调用sub。或者用一个原型('sub my_push(\ @@){...}'),告诉Perl期望一个数组(不是列表!)作为函数的第一个参数,并将它作为函数传递给你的子例程一个数组引用,让你说'my_push @ a,@ b'并让Perl做你的意思。 – mob 2012-01-05 16:42:04