我对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
(不是所有内容,也不是''
),还应该将其标量表示为哈希?
最佳答案
最重要的一点是:列表不会变平。 (列表是平坦的,但它们不会展平,因为这样做必须首先嵌套。)
列表上下文中的,
(逗号运算符)是列表串联。列表上下文中的A , B
评估列表上下文中的A
和B
,然后合并结果。
标量上下文中的A , B
的工作方式类似于C(或JavaScript):它在void上下文中评估A
,然后在标量上下文中评估(并返回)B
。 (void上下文中的A , B
的工作原理相同,但也可以在void上下文中评估B
。)
在return X
中,X
的上下文是函数调用本身的上下文。因此sub my_test { return X } scalar my_test
类似于scalar X
。 就像return
动态地查看当前子调用所在的上下文,并相应地评估其操作数表达式。
perldoc perlsub
says:
A
return
statement may be used to exit a subroutine, optionally specifying the returned value, which will be evaluated in the appropriate context (list, scalar, or void) depending on the context of the subroutine call.)
如上所述,标量上下文中的
@x, @y
在void上下文中评估@x
(对于数组不执行任何操作),然后在标量上下文中评估并返回@y
。标量上下文中的数组会产生其包含的元素数量。同样的逻辑适用于
%defaults, %values, %overrides
。 ,
is left-associative,因此将其解析为(%defaults , %values) , %overrides
。这将在void上下文中评估
%defaults , %values
(反过来评估%defaults
,然后在void上下文中评估%values
,这无效),然后在标量上下文中评估并返回%overrides
。标量上下文中的哈希返回描述哈希内部的(相当无用的)字符串。
关于perl - 为什么标量sub {(@x,@y)}->()返回标量@y?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38550244/