E08094: coalescing expression has a predetermined result - both operands are literals, or a literal on the left of '?:' is always set and so always chosen
What went wrong
This coalescing expression has a result that is predetermined at compile time. Either both sides of a comparison coalescing operator ('<?', '>?') are literal values, or the left of the coalescing operator (Elvis) '?:' is a literal - a literal is always set, so it is always the result and the right is never used. '5 <? 3' is always 3; '7 ?: fallback' is always 7, and 'fallback' is never evaluated. The other way round, 'fallback ?: 7', is fine: the literal is the fallback for an unset 'fallback'. The [EXAMPLE] section below shows each operator with literals, and the same operators over variables.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 1333 (Why does EK9 reject a coalescing expression where both...)
- ek9 -q 2061 (What type does 'a ?: b' have when a and b are different types?)
How to fix it
- Replace one literal with a variable or named constant
- For '?:', put the value that may be unset on the LEFT and the literal default on the right
- If the result is intentional, assign the known value directly
- Check for copy-paste errors in the operands
Common causes
- Copy-paste error (forgot to change one operand)
- Operands of '?:' written the wrong way round ('0 ?: count' for 'count ?: 0')
- Placeholder code that was never completed
- Debugging remnant
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08094: coalescing expression has a predetermined result - both operands are literals, or a literal on the left of '?:' is always set and so always chosen
#!ek9 defines module error.e08094.bad defines function checkIntegerCoalescingLT() <- result as Integer? result: 5 <? 3 checkIntegerCoalescingGT() <- result as Integer? result: 5 >? 3 checkIntegerCoalescingLE() <- result as Integer? result: 5 <? 3 checkIntegerCoalescingGE() <- result as Integer? result: 5 >? 3 checkFloatCoalescingLT() <- result as Float? result: 1.0 <? 2.0 checkStringCoalescingLT() <- result as String? result: "alpha" <? "beta" //A literal on the LEFT of '?:' is always set, so it is always the result and the right is never used. checkElvisIntegerLiteralLeft() -> fallback as Integer <- result as Integer? result: 7 ?: fallback checkElvisPromotedLiteralLeft() <- result as Float? result: 7 ?: 2.5 checkElvisStringLiteralLeft() -> fallback as String <- result as String? result: "text" ?: fallback
Fixed: Coalesce a variable; a literal only as the fallback
#!ek9 defines module error.e08094.good defines function coalesceVariableWithLiteral() -> amount as Integer <- result as Integer? result: amount <? 100 coalesceTwoVariables() -> first as Integer second as Integer <- result as Integer? result: first >? second coalesceVariableLE() -> first as Integer second as Integer <- result as Integer? result: first <? second coalesceVariableGE() -> amount as Integer <- result as Integer? result: amount >? 50 //A literal on the RIGHT of '?:' is the fallback - the left decides. elvisVariableLeftLiteralRight() -> amount as Integer <- result as Integer? result: amount ?: 0 //Inside require/assert a literal on the left is deliberate (as for the comparison family). elvisLiteralLeftInRequire() -> amount as Integer require (7 ?: amount) > 0
Questions and answers
These Q&A entries show E08094 and its fix: