在标量上下文中是否存在列表?

时间:2011-11-22 19:57:05

标签: perl list scalar-context

my $mind = ( 'a', 'little', 'confused' );

这是因为perldoc perlfaq4解释了上面的行如下(强调添加):

  

由于您正在分配标量,因此右侧是标量   上下文。标量上下文中的逗号运算符(是的,它是运算符!)   评估其左侧,抛弃结果并进行评估   它是右侧并返回结果。实际上,那    list-lookalike $scalar分配给它最合适的值。很多人   搞砸了,因为他们选择了 list-lookalike ,其最后一个元素   也是他们期望的计数:

my $scalar = ( 1, 2, 3 );  # $scalar gets 3, accidentally

我理解这意味着在标量上下文中没有列表这样的东西。

但是,ikegami认为它是"result[s] in a list operator, so it is a list literal."

那么,它是否是一个列表?

6 个答案:

答案 0 :(得分:8)

列表文字实际上是在代码中写出的列表,因此(1, 2, 3)是列表文字,而caller例如是一个可以返回列表或标量的函数,具体取决于上下文。

如下所示:

my $x = ...;

...看到标量上下文,因此如果...是列表文字,那么您将在标量上下文中有一个列表文字:

my $x = (1, 2, 3);

但是列表文字不会产生列表,因为它包含的逗号运算符会看到标量上下文,然后导致它返回列表文字的最后一项,并在评估它们之后抛弃剩余的值。

就函数而言,函数本身可以看到它被调用的任何上下文,然后它被传播到该函数返回的任何行。因此,您可以在标量,列表或无效上下文中使用函数,如果该子集的最后一行恰好是列表文字,则该列表文字将看到任何这些上下文并且行为正确。

所以基本上这是一个术语区别,list literal引用实际源代码*中逗号分隔的值列表,list引用放在perl堆栈上的值序列。< / p>

您可以编写具有返回值的子例程,这些返回值的行为类似于数组或类似于上下文的列表文字。

sub returns_like_array  {my @x = 1..5; return @x}

sub returns_like_list   {my @x = 1..5; return @x[0 .. $#x]}

*或导致逗号分隔值列表的内容,例如qw()或胖逗号=>或散列或数组切片。

您还可以在此处查看我的答案:How do I get the first item from a function that returns an array in Perl?,其中详细介绍了列表。

答案 1 :(得分:3)

我同意你和perlfaq4。引用perldata,这可能是关于这一点的权威文件:

  

在不需要列表值的上下文中,似乎列表文字的值只是最终元素的值,与C逗号运算符一样。

(强调我的)。

也就是说,ikegami有权使用他想要的任何术语。不同的人会用不同的术语来思考不同的语言结构,只要最终的结果是相同的,我认为它们的术语与文档中的术语不同并不重要。 (但是,在公共论坛上坚持特殊术语并不是一个好主意!)

答案 2 :(得分:3)

问问Perl!

>perl -MO=Concise,-exec -e"my $s = ($x, $y, $z);"
1  <0> enter
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark v
4  <#> gvsv[*x] s
5  <#> gvsv[*y] s
6  <#> gvsv[*z] s
7  <@> list sKP                      <--- list in (s)calar context.
8  <0> padsv[$s:1,2] sRM*/LVINTRO
9  <2> sassign vKS/2
a  <@> leave[1 ref] vKP/REFC

所以是的,人们可以在标量上下文中一个列表。

在标量上下文中,无法返回列表。 (嗯,有可能来自XS,但程序会崩溃,可能会出现“奇怪的副本”错误。)


它不能是任何其他方式。如果有一个不同的列表op和逗号,则无法编译以下内容:

sub f { "a", "b", "c" }

这会导致列表操作或逗号吗?实际上,没有这样的区别,所以是的,它导致了操作。

答案 3 :(得分:2)

这不是一个清单。由于您要分配标量,因此它是逗号运算符 - 评估左侧,评估右侧,返回右侧,并从左向右解析。 $scalar将为'confused':)

答案 4 :(得分:2)

这是术语和观点的问题。术语在这里很棘手,因为你可以在源代码中写一个列表,返回一个值列表,或者在列表上下文中评估一些东西......而“list”这个词在每种情况下都意味着微妙的不同!

从技术上讲,列表不能存在于标量上下文中,因为perl(解释器)不会为这样的事情创建值列表:

my $x = ('a', 'b', 'c');

pedantic 精确时,这被解释为标量上下文中逗号运算符的行为。类似地,qw被定义为返回标量上下文中的最后一个元素,因此这里没有列表:

my $x = qw(a b c);

在这两种情况下(以及我们可以提出的任何其他运算符示例)我们所说的是解释器不会创建值列表。这是一个实现细节。 perl 没有理由创建一个值列表并抛弃除最后一个之外的所有值;它只是选择不这样做。

Perl语言是抽象的。在源代码级别('a', 'b', 'c')是一个列表。您可以在对其强加标量上下文的表达式中使用该列表,因此从该角度来看,列表可以存在于标量上下文中。

最后,它是[Pp] erl如何运作的心理模型之间的选择。 “标量上下文中的列表返回其最后一个值”模型稍微不准确但更容易理解。据我所知,没有任何角落情况在功能上不正确。 “标量上下文中没有列表这样的东西”模型更准确但更难处理,因为您需要考虑标量上下文中每个运算符的行为。

答案 5 :(得分:1)