我对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(而不是一切,而不是''),但它的标量表示为哈希?
最重要的一点是:列表不会变平.(列表是扁平的,但它们不会变平,因为要这样做,它们必须首先嵌套.)
,列表上下文中的(逗号运算符)是列表连接.A , B在列表上下文中计算A并B在列表上下文中,然后连接结果.
A , B在标量上下文中的工作方式类似于C(或JavaScript):它A在void上下文中进行求值,然后B在标量上下文中求值(并返回).(A , B在void上下文中工作方式相同,但B也在void上下文中进行求值.)
在return X,上下文X是函数调用本身的上下文.因此sub my_test { return X } scalar my_test像scalar X.它就像return动态查看当前子调用所在的上下文,并相应地计算其操作数表达式.
甲
return语句可用于退出子程序,任选指定返回的值,这将在适当的上下文根据子程序调用的上下文(列表中,标量,或空隙)进行评价.)
如上所述,@x, @y在标量上下文中,@x在void上下文中进行求值(对于数组不执行任何操作),然后@y在标量上下文中进行求值和返回.标量上下文中的数组产生它包含的元素数.
同样的逻辑适用于%defaults, %values, %overrides.,是左关联的,所以这解析为(%defaults , %values) , %overrides.这将%defaults , %values在void上下文中进行求值%defaults(然后%values在void上下文中进行求值,然后在void上下文中无效),然后%overrides在标量上下文中求值并返回.标量上下文中的散列返回描述散列内部的(相当无用的)字符串.