在Perl中强制列表上下文

时间:2013-06-16 18:11:26

标签: perl

我正在试图理解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'打印但却没有得到任何结果。这里发生了什么?

3 个答案:

答案 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

回答问题的主体:

当被上下文混淆时,请记住操作符对操作数强加上下文,而不是相反。在您的问题情况下,您有一个标量赋值,为标量分配列表赋值的结果,它将列表赋值放在标量上下文中。要知道发生了什么,只需查看列表赋值将在标量上下文中返回的内容。 (一般来说,运算符返回最常见的内容,这意味着没有一个易于记忆的规则适用于所有运算符。)