标量与Perl中的列表上下文

时间:2011-03-02 16:55:08

标签: perl list scalar

我在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上下文:

这本书说'反向某事'给出了一个列表上下文,所以我猜qw/ yabba dabba doo /被视为列表而reverse qw/ yabba dabba doo /被视为('doo','dabba','yabba')。< / p>

所以$backward = something暗示某事物是标量,所以我期待结果'doo dabba yabba',但它是不同的:'oodabbadabbay'。

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

标量测试输出如何工作?

4 个答案:

答案 0 :(得分: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 =为我们提供标量上下文。这意味着逗号运算符位于第一行的列表上下文中,而第二行的标量上下文。在列表上下文中,comma operator创建一个列表。在标量上下文中,它评估两个操作数并返回右手操作数。这意味着标量上下文中('yabba', 'dabba', 'doo')的值为'doo',这就是分配给$notbackward的值。

答案 1 :(得分:7)

所有Perl函数,包括您定义的任何sub can detect whether they are being called in "scalar" or "list" context,并且有许多函数可以根据此上下文更改其行为。

除了Do Do I Mean之外,很少有关于函数何时以及如何以不同方式处理这两个上下文的约定(这whole thread on 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

(*) - 对标量的注释列表赋值与 array 对标量的赋值不同 - 这是列表数组之间最重要的区别之一

@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"

答案 2 :(得分:3)

对于这一行:

$backward = reverse qw/ yabba dabba doo /;

你正在反向请求标量。反向的perldoc说:

  

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

因此它会返回每个反转的字母。

有关 $ notbackward = qw / yabba dabba doo /; qw的perldoc //说:

  

评估单词列表   从STRING中提取出来,使用   嵌入的空格作为单词   分隔符。它可以理解为   大致相当于:

               split(’ ’, q/STRING/);
     

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

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

答案 3 :(得分:0)

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

这被证明是如此令人困惑,以至于perl6将它们拆分为不同命名的函数。