上下文和逗号运算符

时间:2015-06-04 14:26:00

标签: perl

我的一位同事在声明后使用逗号而不是分号,结果是类似到下面的代码:

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。

对任何一种情况下发生的特定语义的任何澄清都将不胜感激。

2 个答案:

答案 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。对我有意义。

调用子列表或标量上下文并不重要。它不会改变逗号运算符的上下文,在两种情况下都是相同的。