Eric Fossum
Eric Fossum

Reputation: 2461

Perl one line if statement

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

Answers (5)

Negative Zero
Negative Zero

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

Eric Strom
Eric Strom

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

jørgensen
jørgensen

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

Keith Thompson
Keith Thompson

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

David Harris
David Harris

Reputation: 2340

$set = ($set eq "Y") ? "N" : "Y";

should work

Upvotes: 8

Related Questions