5

有一个谎言,标量上下文中的列表产生列表的最后一个元素。这是一个谎言,因为(俗话说)你不能在标量上下文中拥有一个列表。在标量上下文中看起来像列表的东西实际上是标量上下文中的逗号运算符,它在标量上下文中具有不同的行为。

但是,这个逻辑似乎有一个漏洞:空列表(有时称为空列表)。字符()定义为空列表perldoc perlglossary。构造

my $s = ();

是有效代码并undef返回$s. 这似乎没有记录在任何地方perldoc(我没有检查过骆驼),但是很多代码都依赖它,所以我认为它会继续存在。

既然序言已经完成,那么问题来了:如果我们不能在标量上下文中拥有一个列表,那么我们在标量上下文中如何称呼空列表以及不将其称为列表的原因是什么(因为没有逗号在标量上下文中)?

如果你喜欢这个问题,你可能也会喜欢P5P 中正在进行的讨论

4

2 回答 2

7

列表是一个非常通用的词。您可能指的是列表运算符或列表值。

代码中没有逗号,所以没有列表运算符。

代码中没有列表上下文,所以没有列表值。

因此,没有清单

my $s = ();

括号从不创建列表

(仅在赋值运算符的 LHS 上时是间接的。)

我们在标量上下文中如何称呼空列表

Perl 称它为“存根”(如下所示),这就是它的真正含义。它是代码中的一个占位符,不允许放置任何内容。

存根由“空括号”表示,因此这是它的另一个名称。

我称之为坏代码。如果要分配undef,请分配undef

有一个谎言,标量上下文中的列表产生列表的最后一个元素。

不,这是真的。列表值不能存在于标量上下文中,因此留下列表运算符。

列表运算符又名逗号运算符返回标量上下文中列表的最后一个元素。


比较以下。没有提到列表:

>perl -MO=Concise -e"my $s = ();"
6  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
5     <2> sassign vKS/2 ->6
3        <0> stub sP ->4
4        <0> padsv[$s:1,2] sRM*/LVINTRO ->5
-e syntax OK

有提到一个列表

>perl -MO=Concise -e"my @a = ();"
7  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
6     <2> aassign[t2] vKS ->7
-        <1> ex-list lK ->4
3           <0> pushmark s ->4
-           <0> stub lP ->-
-        <1> ex-list lK ->6
4           <0> pushmark s ->5
5           <0> padav[@a:1,2] lRM*/LVINTRO ->6
-e syntax OK

...它与括号无关

>perl -MO=Concise -e"my @a = 's';"
8  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
7     <2> aassign[t2] vKS ->8
-        <1> ex-list lK ->5
3           <0> pushmark s ->4
4           <$> const[PV "s"] s ->5
-        <1> ex-list lK ->7
5           <0> pushmark s ->6
6           <0> padav[@a:1,2] lRM*/LVINTRO ->7
-e syntax OK
于 2011-08-07T04:55:38.060 回答
1

它更像是一个无价值的表达式,相当于undef. 更多示例:

$ perl -we 'print scalar( () )'
Use of uninitialized value in print at -e line 1.

$ perl -we 'print 0+()'
Use of uninitialized value in addition (+) at -e line 1.
于 2011-08-06T21:46:57.750 回答