4

EDIT: For anyone who has arrived here with this issue, I found this documented almost verbatim in the perldoc at https://perldoc.perl.org/perlop#Conditional-Operator

In writing a simple subroutine, I found I kept getting incorrect results using the ternary operator, but correct results using a more simple if statement. I'm sure there is an explanation, but I'm simply not seeing it.

When fed the following input:

my @input = (4, 5, 7, 8, 1, 2, 3, 0);
sum_square_even_root_odd(\@input);

The result should be 91.61.

The following (using Ternary) results in 175.61.

sub sum_square_even_root_odd {
    my ($nums) = @_;
    my $sum = 0;
    map { $_ % 2 ? $sum+= sqrt $_ : $sum += $_ ** 2 } @{$nums};
    return sprintf('%.2f', $sum) + 0;
};

However, the result is what is expected when simply changed to an if statement

sub sum_square_even_root_odd {
    my ($nums) = @_;
    my $sum = 0;
    map { if( $_ % 2 ) { $sum+= sqrt $_ } else { $sum += $_ ** 2 } } @{$nums};
    return sprintf('%.2f', $sum) + 0;
};

Can someone explain why this is happening? I assume a value I am not expecting is sneaking it's way into $_, but I'm unsure as to why.

Thank you!

Myersguy
  • 43
  • 4
  • 1
    It appears the `+=` operator is running for both the succeeding and failing case in the ternary version. Maybe someone else can explain precisely why -- either way, I wouldn't put side effects in `map`. Consider the `sum` function from `List::Util`. – user3243135 Feb 23 '21 at 00:42
  • Thanks for the insight. This may be a precedence issue, but I'd be interested in how to solve for it if it is. I was attempting this challenge without importing any modules, otherwise I absolutely would have simply used List::Util for it. – Myersguy Feb 23 '21 at 00:46

1 Answers1

9

It is, in fact, a precedence issue. The way to diagnose precedence problems is with B::Deparse:

$ perl -MO=Deparse,-p -e 'map { $_ % 2 ? $sum+= sqrt $_ : $sum += $_ ** 2 } @ARGV'
map({((($_ % 2) ? ($sum += sqrt($_)) : $sum) += ($_ ** 2));} @ARGV);
-e syntax OK

Aha, the : has higher precedence than the += to its right. To do what you mean, use parentheses on the last clause of the ternary operation:

$_ % 2 ? $sum+= sqrt $_ : ($sum += $_ ** 2)
mob
  • 117,087
  • 18
  • 149
  • 283