2016-07-24 33 views
9

有几件事我 “知道” 的Perl:为什么标量子{(@x,@y)} - >()返回标量@y?

  • 名单压扁
  • 功能采取并返回列表

所以,如果我有这样的:

sub my_test { 
    my @x = qw(a b c); 
    my @y = qw(x y z t); 
    return (@x, @y); 
} 

say my_test; # a b c x y z t 
say scalar my_test; 

我期望两个结果值中的任一个:

  • 7,因为这是列表qw(a b c x y z t)中有多少项目。事实上,这是我从scalar sub { @{[ qw(a b c x y z t) ]} }->()得到的结果。
  • 't',因为如果你解释逗号作为逗号(叹息)你('a', 'b', 'c', 'x', 'y', 'z', 't')计算结果为't'。的确,这是我从scalar sub { qw(a b c x y z t) }->()得到的结果。

你得到的却是'hellip; 4,没有警告。为什么我会混合列表拼合和逗号运算符?

类似的故事与哈希和这个相当流行的模式:

sub default_override_hash { 
    my %defaults = (foo => 'bar', egg => 'quuz'); 
    my %values = @_; 
    my %overrides = (__baz => ''); 
    return (%defaults, %values, %overrides); 
} 

scalar default_override_hash; # '1/8' 

如何scalar知道default_override_hash返回了3个哈希,它不应该仅仅只得到%overrides(而不是万能的,没有''),但它的标量表示为散列?

+0

我想我希望'标量'就像'sub my_scalar {my @input = @_;标量@scalar; }' – badp

+0

相关:http://stackoverflow.com/q/8232951/133939 – Zaid

回答

7

最重要的一点是:列表不平坦。 (列表是平的,但它们不平坦,因为要做到这一点,它们必须先嵌套。)

,(逗号运算符)在列表上下文中是列表级联。列表上下文中的A , B评估列表上下文中的AB,然后连接结果。

A , B在标量环境的工作原理是C(或JavaScript):它评估A在无效的情况下,然后计算(和返回)B在标量上下文。 (A , B在无效的情况下的工作方式相同,但在无效的情况下评估B了。)

return XX上下文是函数的情况下调用本身。因此sub my_test { return X } scalar my_test就像scalar X这就像return动态查看当前子调用所处的上下文,并相应地评估其操作数表达式。

perldoc perlsub says

return语句可能取决于上下文用于退出子程序,任选指定返回的值,这将在适当的上下文进行评估(表,标量,或空隙)的子程序调用。)

如上所述,@x, @y在标量上下文在无效的情况下(这对于阵列不执行任何计算@x),然后评估和在标量上下文返回@y。标量上下文中的数组产生它包含的元素的数量。

相同的逻辑适用于%defaults, %values, %overrides, is left-associative,所以这解析为(%defaults , %values) , %overrides。 这将在无效上下文中评估%defaults , %values(依次评估%defaults,然后在无效上下文中评估%values,这无效),然后在标量上下文中评估并返回%overrides。标量上下文中的散列返回描述散列内部的(相当无用的)字符串。

+0

粗体句子是错误的。 'return'根本不看上下文。即使这样做,return也会在逗号运算符之后进行求值,所以它在运行时所做的操作对逗号运算符没有任何影响。这意味着说'return'是检查调用者的上下文(或者它是这样的)是完全错误的;这是逗号运算符。 – ikegami

+0

正确的措辞是:**逗号运算符(',')动态查看当前子调用的上下文,并相应地评估其操作数表达式。** – ikegami

+1

@ikegami'return @ z' has no comma但仍然在当前子文档的上下文中评估'@ z'。 – Oktalist

相关问题