Reputation: 2461
I have a statement
$set eq "Y" ? $set = "N" : $set = "Y";
But no matter what it always sets to "N"
# Toggle setting
if ($set eq "Y")
{
$set = "N";
}
else
{
$set = "Y";
}
Why doesn't the one liner seem to work?
Upvotes: 14
Views: 73118
Reputation: 73
If you rather not use "C" style conditional statements, you can do the same thing with 2 lines:
my $set = "Y"; #Set the scope and default value
$set = "N" if ($set eq "Y");
I personally recommend the "C" style described by others above... it easily demonstrates the two options a variable can be.
However, the method I show is great when dealing with a single conditional result.
Upvotes: 5
Reputation: 40142
Due to precedence rules, perl is not parsing your statement as you think:
$ perl -MO=Deparse,-p -e '$set eq "Y" ? $set = "N" : $set = "Y"'
((($set eq 'Y') ? ($set = 'N') : $set) = 'Y');
-e syntax OK
So as you see, in both conditions, the final result is the $set
scalar which then gets set to Y
.
You can fix it with a few parens:
$set eq "Y" ? $set = "N" : ($set = "Y")
But why repeat the assignment:
$set = $set eq 'Y' ? 'N' : 'Y';
Upvotes: 32
Reputation: 10549
It's about precedence; let's do the intent with parenthesis, and then let Perl remove them again:
perl -MO=Deparse -e '($set eq "Y") ? ($set = "N") : ($set = "Y"); print $set'
$set eq 'Y' ? $set = 'N' : ($set = 'Y');
print $set;
-e syntax OK
Which is thus the parenthesing required to do as you intended.
Upvotes: 5
Reputation: 263257
Operator precedence. What you've written is equivalent to
($set eq "Y" ? $set = "N" : $set) = "Y";
If you insist on writing such terse code, this make more sense:
$set = ( $set eq "Y" ? "N" : "Y" );
Upvotes: 9