I am facing following problem Perl conditional (ternary) operator does no shortcut evaluation

How this problem occurs ?

the ternary operator is a substitute for if … else. I always thought so, but recently I have a logical problem with that.

Consider this short debug session:

  DB<1> $s='X'

  DB<2>  1 ? $s .= '_' : $s = '_'

  DB<3> x $s
0  '_'

So if 1 is true, then the expression $s .= '_' should be evaluated (and not $s = '_'). But why is $s just '_' at the end.

Solution 1

Here The ternary conditional operator (?:) has a higher precedence than the assignment operator (=) (the table of the precedence of Perl’s operator can be found in the Operator Precedence and Associativity section of perlop). As such, the line

1 ? $s .= '_' : $s = '_'

is parsed by Perl as

(1 ? ($s .= '_') : $s) = '_'

(You can check that by yourself by running perl -MO=Deparse <your program>)

Note also that $s .= '_' returns $s with the added _ at the end, and that this $s can be assigned to (in technical terms, it’s an lvalue). This is documented in the Assignment Operators section of perlop:

Unlike in C, the scalar assignment operator produces a valid lvalue. Modifying an assignment is equivalent to doing the assignment and then modifying the variable that was assigned to.

So, basically, your code is doing

($s .= '_') = '_';

Which is equivalent to

$s .= '_';

Solution 2

Here it is an issue of operator precedence.

$ perl -MO=Deparse,-p -e '   
> $s='X';
> $t=1;
> $t ? $s .= '_' : $s = '_';
> print $s'
($s = 'X');
($t = 1);
(($t ? ($s .= '_') : $s) = '_');
print($s);
-e syntax OK

Whether the ternary condition is true or false, ultimately $s is set to "_".

To do what you intend to do, you need to add at least one set of parentheses:

1 ? $s .= '_' : ($s = '_');
  1. Perl conditional (ternary) operator does no shortcut evaluation

    Here The ternary conditional operator (?:) has a higher precedence than the assignment operator (=) (the table of the precedence of Perl's operator can be found in the Operator Precedence and Associativity section of perlop). As such, the line

  2. Perl conditional (ternary) operator does no shortcut

    Here The ternary conditional operator (?:) has a higher precedence than the assignment operator (=) (the table of the precedence of Perl's operator can be found in the Operator Precedence and Associativity section of perlop). As such, the line

So here is all solution about Perl conditional (ternary) operator does no shortcut evaluation.