The conditional (ternary) operator suggests 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?
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 .= '_';
$s = '_';