【问题标题】:Forcing a list context in Perl在 Perl 中强制列表上下文
【发布时间】:2013-06-12 17:46:31
【问题描述】:

我试图理解 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' 被打印出来,但什么也没得到。这里发生了什么?

【问题讨论】:

  • 这是一个很好的问题 -- +1 -- 但我认为这确实是 List Assignment in Scalar Context 的复制品,它有很好的答案,你应该去看看。
  • 我去看看。谢谢!
  • use warnings 会给你一些线索。

标签: perl


【解决方案1】:

您会感到困惑,因为您认为= 是单个运算符,而它可能导致两个不同的运算符:列表赋值运算符或标量赋值运算符。 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 将在列表上下文中调用,但整体将只返回返回列表的一个元素。

【讨论】:

  • 添加了一点“强制列表上下文”。
【解决方案2】:

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

【讨论】:

  • 我认为标量上下文中的列表会返回列表的最后一项。我会参考另一个参考来仔细检查。
  • 标量上下文中的列表assignment;不是标量上下文中的列表(请参阅我的答案)
  • 是的,我现在看到了区别!谢谢。
【解决方案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

回答问题的主体:

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

【讨论】:

  • 根据the documentation for scalar,“没有等效的运算符来强制在列表上下文中插入表达式[原文如此],因为在实践中,这是不需要的。如果你真的想这样做,但是,您可以使用构造 @{[ (some expression) ]} ,但通常一个简单的 (some expression) 就足够了。”
  • 我的回忆是scalar(()=...)效率更高,但是如果arrayref的方式更清晰,那就用吧
猜你喜欢
  • 1970-01-01
  • 2011-01-02
  • 2014-09-24
  • 2014-03-29
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
相关资源
最近更新 更多