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

bad*_*adp 9 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;
Run Code Online (Sandbox Code Playgroud)

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

  • 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'
Run Code Online (Sandbox Code Playgroud)

如何scalar知道default_override_hash返回三个哈希值,它不仅应该只获取%overrides(而不是一切,而不是''),但它的标量表示为哈希?

mel*_*ene 7

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

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

A , B在标量上下文中的工作方式类似于C(或JavaScript):它A在void上下文中进行求值,然后B在标量上下文中求值(并返回).(A , B在void上下文中工作方式相同,但B也在void上下文中进行求值.)

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

perldoc perlsub:

return语句可用于退出子程序,任选指定返回的值,这将在适当的上下文根据子程序调用的上下文(列表中,标量,或空隙)进行评价.)

如上所述,@x, @y在标量上下文中,@x在void上下文中进行求值(对于数组不执行任何操作),然后@y在标量上下文中进行求值和返回.标量上下文中的数组产生它包含的元素数.

同样的逻辑适用于%defaults, %values, %overrides.,是左关联的,所以这解析为(%defaults , %values) , %overrides.这将%defaults , %values在void上下文中进行求值%defaults(然后%values在void上下文中进行求值,然后在void上下文中无效),然后%overrides在标量上下文中求值并返回.标量上下文中的散列返回描述散列内部的(相当无用的)字符串.