我知道的一些事情"关于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
(而不是所有内容,而不是''
),而是它的标量表示为哈希?
答案 0 :(得分:7)
最重要的一点是:列表不会变平。 (列表是扁平的,但它们不会变平,因为要做到这一点,它们必须首先嵌套。)
列表上下文中的 ,
(逗号运算符)是列表连接。列表上下文中的A , B
评估列表上下文中的A
和B
,然后连接结果。
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
动态查看当前子调用所在的上下文,并相应地计算其操作数表达式。
可以使用
return
语句退出子例程,可选地指定返回值,该值将根据子例程调用的上下文在适当的上下文(列表,标量或void)中进行计算。)
如上所述,标量上下文中的@x, @y
在void上下文中评估@x
(对于数组不执行任何操作),然后在标量上下文中计算并返回@y
。标量上下文中的数组产生它包含的元素数。
同样的逻辑适用于%defaults, %values, %overrides
。 ,
is left-associative,因此解析为(%defaults , %values) , %overrides
。
这将在void上下文中评估%defaults , %values
(后者反过来评估%defaults
,然后在void上下文中评估%values
,这无效),然后在标量上下文中计算并返回%overrides
。标量上下文中的散列返回描述散列内部的(相当无用的)字符串。