Why must I put parentheses around '?:' when I mix it with '+' or '=='?
← Operators and Expressions · Ref: Q2060
EK9 never lets a coalescing operator - null coalescing '??', 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 '??' 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, and so does 'first ?? second + fallback' - write '(first ?? second) + fallback'.
See Q1091 for the coalescing operator (Elvis), Q1093 for chained coalescing and Q2061 for the operand types coalescing accepts.
Example
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}`)
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:
chained <- first ?: second ?? fallback
Correct:
chained <- 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: operator mixing, <?, coalescing, E08269, elvis, parentheses, ?:, precedence