为什么通过ref需要转移而不是@_?

时间:2013-04-08 00:29:46

标签: perl

我有一个关于通过引用Perl中的子例程的问题。对于值,如果我使用@_传递它可以工作但是对于ref只有shift工作。不知道为什么。我有以下给出的示例代码:

这有效:

#! /usr/bin/perl

use strict;
use warnings;

my $name = 'John';
PassScalarByRef( \$name );

sub PassScalarByRef{
    my $got = shift;
    print "Hello $$got\n";
}

但不是这一个:

#! /usr/bin/perl

use strict;
use warnings;

my $name = 'John';
PassScalarByRef( \$name );

sub PassScalarByRef{
    my $got = @_;
    print "Hello $$got\n";
}

4 个答案:

答案 0 :(得分:13)

在第二种情况下,分配给$got会为@_提供标量上下文,从而使其评估其大小(元素数量)。你可以说:

my ($got) = @_;

...按照您的预期将@_的第一个元素分配给$got

答案 1 :(得分:6)

您在标量上下文中使用@_数组。 $got现在包含传递的参数数量。您应该尝试my ($got) = @_,现在使用列表上下文中的数组,这就是您的意思。

答案 2 :(得分:3)

大多数操作员以一致的方式为其操作数提供特定的上下文;例如,+给出了它的操作数标量上下文; ||给出了左操作数标量上下文及其右操作数||本身具有的任何上下文。

分配略有不同,因为有两种类型,列表赋值和标量赋值。

标量分配如下:

$scalar = ...
lvaluesub() = ...

(lvalue subs是perl的一个很少使用的特性;内置pos就是一个例子。)

只分配了一个值,这些值赋予=右操作数标量上下文。

列表分配如下所示:

@array = ...
@arraytoslice[...] = ...
%hash = ...
@hashtoslice{...} = ...
( ... ) = ...

甚至

() = ...

所有这些都需要一个要分配的值列表,因此请给出正确的操作数列表上下文。

当你说:

my $got = @_;

这是一个标量赋值,因此@_得到标量上下文,这会导致它返回元素数,而不是第一个值。

相反,请说:

my ($got) = @_;

有些人持续这样做,即使是只有一个操作数的潜艇;其他人

my $param1 = shift;
my $param2 = shift;

用于具有少量操作数的subs。

使用shift获取对象/类的方法和来自@_的列表赋值对于其余参数来说很常见。

答案 3 :(得分:0)

使用不同。

我的$ got = $ _ [0];