Why must I put parentheses around '?:' when I mix it with '+' or '=='?
← Operators and Expressions · Ref: Q2060
EK9 never lets a coalescing operator - coalesce (Elvis) '?:' or the comparison coalescing operators '<?', '>?' - mix with a different binary operator without parentheses (E08269). '?:' binds tighter than arithmetic, comparison and logic, so 'first + second ?: fallback' would be 'first + (second ?: fallback)': when first is unset the sum is unset and the fallback never applied to it. Kotlin puts '?:' below '+', C# and JavaScript put their '??' below '==', so whichever reading you expect, a reader from another language expects the other. The parentheses say which one you mean:
sumOrFallback <- (first + second) ?: fallback firstPlusEither <- first + (second ?: fallback)
A chain of the SAME operator reads one way only and needs no parentheses:
chained <- first ?: second ?: fallback
'?:' and '<?' are different operators, so 'first ?: second <? fallback' needs parentheses too - write '(first ?: second) <? fallback'.
See Q1091 for the coalescing operator (Elvis), Q1093 for chained coalescing and Q2061 for the operand types coalescing accepts.
Example
#!ek9 defines module qa.operators.coalescingparentheses defines function reading() -> start as Integer <- rtn as Integer: start defines program CoalescingParenthesesDemo() stdout <- Stdout() first <- reading(Integer()) second <- reading(5) fallback <- reading(100) //The sum is unset because first is unset, so the fallback is taken. sumOrFallback <- (first + second) ?: fallback stdout.println(`(first + second) ?: fallback = ${sumOrFallback}`) //Only second is defaulted; first is still unset, so the sum is unset. firstPlusEither <- first + (second ?: fallback) firstSet <- firstPlusEither? stdout.println(`first + (second ?: fallback) is set: ${firstSet}`) chained <- first ?: second ?: fallback stdout.println(`first ?: second ?: fallback = ${chained}`) //Two DIFFERENT coalescing operators need parentheses too. lesser <- (first ?: second) <? fallback stdout.println(`(first ?: second) <? fallback = ${lesser}`)
Common mistakes
E08269 — '?:' binds tighter than '+', so this would be 'first + (second ?: fallback)'. Parenthesise whichever operator is meant to apply first. See ek9 -h E08269 for details.
Incorrect:
sumOrFallback <- first + second ?: fallback
Correct:
sumOrFallback <- (first + second) ?: fallback
E08269 — '?:' and '<?' are different operators, so mixing them needs parentheses; a chain of the same operator does not. See ek9 -h E08269 for details.
Incorrect:
lesser <- first ?: second <? fallback
Correct:
lesser <- (first ?: second) <? fallback
Other ways to ask this
- What does error E08269 mean?
- Does '?:' bind tighter than '+' in EK9?
- Why is 'total <- first + second ?: fallback' a compile error?
- Can I mix '<?' with arithmetic without brackets?
- What is the precedence of the Elvis operator in EK9?
Coming from another language?
Kotlin: 'a + b ?: c' is '(a + b) ?: c' ('?:' is below '+'). C#/JavaScript: 'a + b ?? c' is '(a + b) ?? c', and JavaScript made mixing '??' with '||'/'&&' a SyntaxError. EK9 applies that JavaScript rule to '?:' and the '<?' family against every other binary operator.
Keywords: <?, ?:, E08269, coalescing, elvis, operator mixing, parentheses, precedence