Hunter McMillen
Hunter McMillen

Reputation: 61540

Context and the Comma Operator

One of my colleagues used a comma after a statement instead of a semi-colon, what resulted was similar to the below code:

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;
}

At first I was surprised that this passed perl -c, then I remembered the comma operator and thought I understood what was going on, but the results of the two print statements below made me doubt again.

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' )}

This call was made in scalar context and the result that I get is the expected result. The comma operator evaluated the LHS of the comma discarded, then evaluated the RHS. I don't believe that it can return the value of the RHS here, because evaluating the return statements leaves the subroutine.

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' )}]

This call was made in list context but the result I get is effectively the same as the call in scalar context. What I think is happening here: Both arguments are evaluated since the sub was called in list context, when the RHS is evaluated the return statement is executed so the LHS is effectively discarded.

Any clarification on the specific semantics that happen in either case would be appreciated.

Upvotes: 2

Views: 90

Answers (2)

ikegami
ikegami

Reputation: 386501

Your explanation is accurate.

The context in which _translate_to_engine is called affects is the context in which all final expressions of the function are evaluated, including the argument to all return. There are two expressions affected in this case: the comma you mentioned, and \%mapped_hash.

In the first test, the returned value is \%mapped_hash evaluated in scalar context. And in the second, the returned value is \%mapped_hash evaluated in list context. \%mapped_hash evaluates to a reference to the hash, regardless of context. As such, the result of the sub is the same regardless of context.

Upvotes: 1

Dondi Michael Stroma
Dondi Michael Stroma

Reputation: 4800

The LHS of the expression is $mapped_hash{$SPECIAL_FIELD} = FakeObject->new(...) and the RHS is return \%mapped_hash. As you said, the comma operator evaluates the left hand side (which assigns a FakeObject instance to the hash key d), and then evaluates the right hand side, causing the sub to return the hashref. Makes sense to me.

Calling the sub in list or scalar context doesn't matter. It isn't going to change the context of the comma operator, which is the same in both cases.

Upvotes: 0

Related Questions