Wandering Thoughts archives

2012-04-11

Faking (or not) a ternary if operator with && and ||

Suppose that you have a multiline if in some language and you want to rewrite this into a single line and a single expression; however, your language only has && and || operators without a ternary if operator (this is C's ?: operator). Can you do this rewrite safely?

To be concrete, let's do this in the Bourne shell (which is where I saw this be done recently). Suppose you have the following multiline bit of shell script and you want to reduce it to something that's as short as possible:

if cmd1; then
  cmd2
else
  cmd3
fi

Is a good translation of this 'cmd1 && cmd2 || cmd3'?

(Let's ignore the set -e gotcha.)

The answer is no. It's easy to see why this is if I rewrite this with specific commands:

true && false || echo oops

This will echo 'oops'.

The answer to the question turns out to depend on whether you care about the value of the ternary if (or the multiline if). If you don't care about the value and are evaluating things purely for their side effects, then you can write 'a ? b : c' as 'a && (b || true) || c', which avoids the problem by forcing the middle clause to always be considered true. If you do need to expose the (truth) value of b, this rewrite is no good and you are almost certainly up the creek; the only way out is if you know that b's value will always considered true.

(I first saw this problem in Python, but seeing it reappear in the Bourne shell started me down the path of thinking about the general issue.)

The Bourne shell version of this rewrite would be

cmd1 && (cmd2 || true) || cmd3

I think that most of the time this should be fine; it would be very odd style to check the exit code of cmd2 or cmd3 after the if, and certainly the example I saw this in didn't do it. My one twitch is that I am reflexively nervous about () potentially introducing surprise subshells, but if cmd2 is a real command that's irrelevant.

programming/TernaryIfVsAndOr written at 01:15:38; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.