在Perl中强制列表上下文

在Perl中强制列表上下文,perl,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 因为第二次打印返回了列表的长度,所以我假设在某个地方生

我试图理解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

因为第二次打印返回了列表的长度,所以我假设在某个地方生成了一个数组,因为标量上下文中的数组计算为其长度。但第四份印刷品似乎与这一假设不符。我本来希望看到
'332211'
打印出来,但是没有得到任何结果。这里发生了什么?

标量上下文中的列表赋值返回右侧的元素数(案例2)。案例4首先将
(33,22,11)
赋值给
()
,然后将
()
(其值未更改)赋值给
@b

,回答标题中的隐含问题:

Perl提供了一个
标量
内置函数,在不使用标量上下文时强制使用标量上下文;类似的
列表
内置不存在,我认为这主要是因为它可能意味着许多不同的东西,例如:

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
回答问题的主体:


当被上下文弄糊涂时,请记住,运算符对操作数施加上下文,而不是相反。在您的问题案例中,您有一个标量赋值,将列表赋值的结果赋给标量,从而将列表赋值置于标量上下文中。要知道发生了什么,只需在标量上下文中查找列表赋值将返回什么。(通常,运算符返回最符合常识的运算符,这意味着没有一个易于记忆的规则适用于所有运算符。)

您感到困惑,因为您认为
=
是一个运算符,而它可能会导致两个不同的运算符:列表赋值运算符或标量赋值运算符。解释差异

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--但我认为它实际上是的副本,它有很多很好的答案,您应该去看看。我来看看。谢谢<代码>使用警告会给你一些线索。我认为标量上下文中的列表会返回列表的最后一项。我将参考另一个有关双重检查的引用。标量上下文中的列表赋值;不是标量上下文中的列表(参见我的答案)是的,我现在看到了区别!谢谢。根据“在列表上下文中没有等价的运算符来强制表达式被插入[sic],因为在实践中,这是不需要的。但是,如果你真的想这样做,你可以使用构造
@{[(某些表达式)]}
,但通常一个简单的
(某些表达式)
就足够了。”我记得
标量(()=…)
更有效,但是如果arrayref方法更清晰,请在“强制列表上下文”中添加一点。
( EXPR )[0]
( EXPR )[-1]