我正在试图理解Perl的背景,我绊倒了一块石头;
鉴于代码;
#!/usr/bin/perl
my $b = (33,22,11);
print "$b\n";
my $b = () = (33,22,11);
print "$b\n";
my @b = (33,22,11);
print "@b\n";
my @b = () = (33,22,11);
print "@b\n";
结果是(最后一行是空白的);
11
3
33 22 11
<>
由于第二次打印返回了列表的长度,我假设某个数组已生成,因为标量上下文中的数组会计算它的长度。但第4版似乎相信这一假设。我期待看到'33 22 11'
打印但却没有得到任何结果。这里发生了什么?
答案 0 :(得分:16)
您感到困惑,因为您认为=
是单个运算符,而它可能导致两个不同的运算符:列表赋值运算符或标量赋值运算符。 Mini-Tutorial: Scalar vs List Assignment Operator解释了这些差异。
my $b = (33,22,11);
------------------ Scalar assign in void context.
---------- List literal in scalar context. Returns last.
my @b = (33,22,11);
------------------ List assign in void context.
---------- List literal in list context. Returns all.
my $b = ( () = (33,22,11) );
--------------------------- Scalar assign in void context.
------------------- List assign in scalar context. Returns count of RHS
---------- List literal in list context. Returns all.
my @b = ( () = (33,22,11) );
--------------------------- List assign in void context.
------------------- List assign in list context. Returns LHS.
---------- List literal in list context. Returns all.
至于你的头衔,强制列表上下文是不可能的。如果函数在期望标量时返回一个列表,则会在堆栈上产生额外的值,这会导致运算符得到错误的参数。
但是,您可以执行以下操作:
( EXPR )[0]
或
( EXPR )[-1]
EXPR
将在列表上下文中调用,但整个将只返回返回列表中的一个元素。
答案 1 :(得分:6)
标量上下文中的列表赋值返回右侧的元素数(案例2)。案例4首先将(33, 22, 11)
分配给()
,然后将()
(其值未更改)分配给@b
。
答案 2 :(得分:3)
回答标题中隐含的问题:
Perl提供scalar
内置函数来强制标量上下文,否则将无法使用;一个类似的list
内置不存在,我想象很大程度上是因为它可能意味着许多不同的东西,例如:
list { code to execute in list context };
可能已定义:
sub list (&) { scalar( () = $_[0]->() ) } # return count of elements
sub list (&) { ( $_[0]->() )[0] } # return first element
sub list (&) { ( $_[0]->() )[-1] } # return last element
sub list (&) { for( $_[0]->() ) {} } # return nothing
回答问题的主体:
当被上下文混淆时,请记住操作符对操作数强加上下文,而不是相反。在您的问题情况下,您有一个标量赋值,为标量分配列表赋值的结果,它将列表赋值放在标量上下文中。要知道发生了什么,只需查看列表赋值将在标量上下文中返回的内容。 (一般来说,运算符返回最常见的内容,这意味着没有一个易于记忆的规则适用于所有运算符。)