为什么标量子{(@ x,@ y)} - >()返回标量@y?

时间:2016-07-24 08:48:51

标签: perl

我知道的一些事情"关于Perl:

  • 列出展平
  • 函数获取并返回列表

所以,如果我有这个:

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) }->()得到的。

你得到的是...... 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返回了三个哈希值,它不仅应该只获取%overrides(而不是所有内容,而不是''),而是它的标量表示为哈希?

1 个答案:

答案 0 :(得分:7)

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

列表上下文中的

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

标量上下文中的

A , B与C(或JavaScript)类似:它在void上下文中计算A,然后在标量上下文中计算(并返回)B。 (A , B在void上下文中的作用相同,但也在void上下文中评估B。)

return X中,X的上下文是函数调用本身的上下文。因此sub my_test { return X } scalar my_test就像scalar X就像return动态查看当前子调用所在的上下文,并相应地计算其操作数表达式。

perldoc perlsub says

  

可以使用return语句退出子例程,可选地指定返回值,该值将根据子例程调用的上下文在适当的上下文(列表,标量或void)中进行计算。)

如上所述,标量上下文中的@x, @y在void上下文中评估@x(对于数组不执行任何操作),然后在标量上下文中计算并返回@y。标量上下文中的数组产生它包含的元素数。

同样的逻辑适用于%defaults, %values, %overrides, is left-associative,因此解析为(%defaults , %values) , %overrides。 这将在void上下文中评估%defaults , %values(后者反过来评估%defaults,然后在void上下文中评估%values,这无效),然后在标量上下文中计算并返回%overrides。标量上下文中的散列返回描述散列内部的(相当无用的)字符串。