3

我在 O'Reilly 的书中发现了一个有点奇怪的例子:

@backwards = reverse qw/ yabba dabba doo /;
print "list context: @backwards\n";
$backward = reverse qw/ yabba dabba doo /;
print "scalar1 context: $backward\n";
$notbackward = qw/ yabba dabba doo /;
print "scalar2 context: $notbackward\n";
print "print context: ",reverse qw/ yabba dabba doo /;
print "\n";

输出是:

list context: doo dabba yabba
scalar1 context: oodabbadabbay
scalar2 context: doo
print context: doodabbayabba

我不明白的是scalar1上下文:

这本书说'reverse something'给出了一个列表上下文,所以我猜qw/ yabba dabba doo /它被视为一个列表和reverse qw/ yabba dabba doo /('doo','dabba','yabba')。

所以来了$backward = something,这意味着某事是一个标量,所以我期待结果'doo dabba yabba',但它是不同的:'oodabbadabbay'。

我想,原因是不能直接将列表设置为标量。所以我做了scalar2测试:只打印列表中的最新项目。为什么?为什么不在 scalar1 测试中?

标量测试输出如何工作?

4

4 回答 4

10

首先,qw/ yabba dabba doo /只是('yabba', 'dabba', 'doo'). 他们的意思是一样的。

reverse函数接受一个列表。在列表上下文中,它反转列表。在标量上下文中,它执行join('', @list)然后反转该字符串中的字符并返回它。

请记住

$backward = reverse qw/ yabba dabba doo /;
$notbackward = qw/ yabba dabba doo /;

方法

$backward = reverse ('yabba', 'dabba', 'doo');
$notbackward = ('yabba', 'dabba', 'doo');

reverse函数提供列表上下文并$notbackward =为我们提供标量上下文。这意味着逗号运算符位于第一行的列表上下文和第二行的标量上下文中。在列表上下文中,逗号运算符创建一个列表。在标量上下文中,它计算两个操作数并返回右侧的操作数。这意味着('yabba', 'dabba', 'doo')标量上下文中的值是'doo',这就是分配给 的值$notbackward

于 2011-03-02T17:07:42.127 回答
7

所有 Perl 函数,包括sub您定义的任何 's,都可以检测它们是在“标量”还是“列表”上下文中被调用,并且有许多函数会根据此上下文改变它们的行为。

除了 Do What I mean 之外,关于函数何时以及如何以不同方式处理这两个上下文的约定很少(perlmonks上的整个线程对这些问题进行了很好的讨论),因此您需要依赖每个函数的文档猜测一个函数在特定上下文中会做什么。

专门针对您的四个示例,

1. @backwards = reverse qw/ yabba dabba doo /
2. $backward = reverse qw/ yabba dabba doo /
3. $notbackward = qw/ yabba dabba doo /;
4. print ..., reverse qw/ yabba dabba doo /;

行为是

1. reverse function, list context:     returns list of the elements in reverse order

2. reverse function, scalar context:   concatenate argument list to a string,
                                       return reverse of that string

3. list assignment to scalar:          returns last element in list (*)

4. also reverse function, list context    same as #1

(*) - 注意列表赋值给标量不同于数组赋值给标量——这是列表数组之间最重要的区别之一:

@a = ("x", "y", "z");  $n = @a;   # array assignment,  $n is array size, or "3"
$n = ("x", "y", "z");             # list assignment,   $n is last element, or "z"
于 2011-03-02T17:22:33.567 回答
3

对于线路:

$backward = reverse qw/ yabba dabba doo /;

您从反向请求一个标量。反向的 perldoc 说:

在标量上下文中,连接 LIST 的元素并返回一个字符串值,其中所有字符的顺序相反。

所以它返回每个颠倒的字母。

对于 $notbackward = qw/ yabba dabba doo /; qw// 的 perldoc 说:

使用嵌入的空格作为单词分隔符,计算从 STRING 中提取的单词列表。可以理解为大致等价于:

               split(’ ’, q/STRING/);

不同之处在于它在编译时生成一个真实列表,而在标量上下文中它返回列表中的最后一个元素。

所以请求标量只返回列表中的最后一项。

于 2011-03-02T17:08:32.143 回答
0

为了简化其他答案, reverse 实际上做了两件事,列表反转和字符串反转。

事实证明这非常令人困惑,以至于 perl6 将它们拆分为不同命名的函数。

于 2011-03-03T00:22:35.347 回答