Ternary Operator
In Phix the ternary operator, also known (if you’ll forgive the redundant tautology) as an if-and-only-if expression,
has a function-call-like syntax, allowing conditional selection with short-circuit evaluation, eg:
If you prefer,
The construct is a simplified form of the if statement with a single condition and an else clause, except that it has two expressions rather than two statement blocks, and not only utilises short-circuit evaluation within the condition, but also evaluates only one of the expressions (aka lazy evaluation [see technicalia]). If the value of the condition can be determined at compile-time (possibly via constant propagation) then the compiler may only emit executable code for one of the expressions as well.
Note that some optimisations, especially pass-by-reference, can be thwarted by incorrect or excessive use of iff, for example
One more example (from builtins\regex.e)
iff(flag?"true":"false")which, fairly obviously, yields "true" or "false" depending on the value of flag. (printf()’s %t does exactly that)
If you prefer,
iif
is exactly equivalent to iff
, additionally comma separators are also valid:
iif(<condition>,<expression1>,<expression2>)However, for me, comma separators make it look too much like a normal function call and I would automatically assume eager evaluation.
The construct is a simplified form of the if statement with a single condition and an else clause, except that it has two expressions rather than two statement blocks, and not only utilises short-circuit evaluation within the condition, but also evaluates only one of the expressions (aka lazy evaluation [see technicalia]). If the value of the condition can be determined at compile-time (possibly via constant propagation) then the compiler may only emit executable code for one of the expressions as well.
Note that some optimisations, especially pass-by-reference, can be thwarted by incorrect or excessive use of iff, for example
s = iff(x<y?append(s,x):append(s,y))is likely to be exponentially slower (you would still need millions of calls to notice) than the much neater and more obvious
s = append(s,iff(x<y?x:y))Often the result of an iff expression is best stored in a suitably named variable, to make the code easier to understand, and quite probably easier to debug, eg:
s = append(s,iff(x<y?l-x*4:l-((x-1)*w+floor(y/w)*4))vs:
integer extra_space = iff(x<y?l-x*4:l-((x-1)*w+floor(y/w)*4) s = append(s,extra_space)Such explicit clarifications normally incur no additional penalty whatsoever1 over the hidden unnamed temporary variable that the compiler would otherwise use anyway.
One more example (from builtins\regex.e)
if greedy then code &= {SPLIT, i+3, nil} else code &= {SPLIT, nil, i+3} end ifhas a certain clarity that, for me, gets lost in
code &= {SPLIT, iff(greedy ? i+3 : nil ), iff(greedy ? nil : i+3 )}I believe this (one of several possible variations) is somewhat better
code &= iff(greedy ? {SPLIT, i+3, nil} : {SPLIT, nil, i+3} )nevertheless I still prefer the longhand/old school version - but use your own judgement, of course.
|
if,
append |