0

我有一个关于通过引用 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

4 回答 4

13

在第二种情况下,分配 to$got提供了一个标量上下文 to @_,这导致它评估它的大小(元素数)。你可以改为说:

my ($got) = @_;

...分配 to 的第一个元素@_$got正如您所期望的那样。

于 2013-04-08T00:33:13.330 回答
6

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

于 2013-04-08T00:33:24.520 回答
3

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

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

标量赋值如下所示:

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

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

只分配了一个值,这些值给出了=正确的操作数标量上下文。

列表分配如下所示:

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

甚至

() = ...

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

当你说:

my $got = @_;

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

相反,说:

my ($got) = @_;

有些人始终如一地这样做,即使对于只有一个操作数的 subs 也是如此;其他人做

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

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

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

于 2013-04-08T01:14:39.677 回答
0

使用方式不同。

我的 $got = $_[0];

于 2013-04-08T01:13:25.153 回答