我的一位同事在声明后使用逗号而不是分号,结果是类似到下面的代码:
my $SPECIAL_FIELD = 'd';
my %FIELD_MAP = (
1 => 'a',
2 => 'b',
3 => 'c',
);
sub _translate_to_engine {
my ($href) = @_;
my %mapped_hash
= map { $FIELD_MAP{$_} => $href->{$_} } keys %$href;
$mapped_hash{$SPECIAL_FIELD} = FakeObject->new(
params => $mapped_hash{$SPECIAL_FIELD}
), # << comma here
return \%mapped_hash;
}
起初我感到惊讶的是,这已经过了perl -c
,然后我想起了comma operator
并认为我理解发生了什么,但下面两个印刷声明的结果让我再次怀疑。
my $scalar_return = _translate_to_engine(
{ 1 => 'uno', 2 => 'dos', 3 => 'tres' }
);
print Dumper $scalar_return;
# {'c' => 'tres','a' => 'uno','b' => 'dos','d' => bless( {}, 'FakeObject' )}
此调用是在标量上下文中进行的,我得到的结果是预期结果。逗号运算符评估丢弃的逗号的LHS,然后评估RHS。我不相信它可以在这里返回RHS的值,因为评估return语句会离开子例程。
my @list_return = _translate_to_engine(
{ 1 => 'uno', 2 => 'dos', 3 => 'tres' }
);
print Dumper \@list_return;
# [{'c' => 'tres','a' => 'uno','b' => 'dos','d' => bless( {}, 'FakeObject' )}]
此调用是在列表上下文中进行的,但我得到的结果实际上与标量上下文中的调用相同。 我认为这里发生的事情:由于在列表上下文中调用了sub,因此评估了两个参数,当评估RHS时,执行return语句以便有效地丢弃LHS。
对任何一种情况下发生的特定语义的任何澄清都将不胜感激。
答案 0 :(得分:1)
您的解释准确无误。
调用_translate_to_engine
的上下文影响是评估函数的所有最终表达式的上下文,包括所有return
的参数。在这种情况下,有两个表达式受到影响:您提到的逗号和\%mapped_hash
。
在第一个测试中,返回的值是在标量上下文中计算的\%mapped_hash
。在第二个中,返回值是\%mapped_hash
在列表上下文中评估。无论上下文如何,\%mapped_hash
都会评估对哈希的引用。因此,无论上下文如何,sub的结果都是相同的。
答案 1 :(得分:0)
表达式的LHS为$mapped_hash{$SPECIAL_FIELD} = FakeObject->new(...)
,RHS为return \%mapped_hash
。如上所述,逗号运算符计算左侧(将FakeObject实例分配给散列键d
),然后计算右侧,使sub返回hashref。对我有意义。
调用子列表或标量上下文并不重要。它不会改变逗号运算符的上下文,在两种情况下都是相同的。