What are the names of EK9's '?' operators - '?', '<-', ':=', ':=?', '?:' and '<?'?
← Operators and Expressions · Ref: Q2004
One name per symbol, used everywhere in EK9:
- 'x?' is the SET-CHECK: true when x holds a meaningful value
- '<-' is a DECLARATION; in an if/switch/for/while/do/try head it is a DECLARATION GUARD (enter only if set)
- ':=' (also '=' and ':') is an ASSIGNMENT; in a head it is blind, so add 'then x?'
- ':=?' is ASSIGN-IF-UNSET: it fills the target only if it is unset ('a :=? b' is 'a := a ?: b')
- '?:' is COALESCE (Elvis): the left if set, otherwise the right, evaluated only then
- '<?' '<=?' '>?' '>=?' are COMPARISON COALESCING: they return one of their operands - the set one, or the lesser/greater
A GUARD is the idea 'enter only if set' - like Swift's 'if let'. There is no '?=' operator and no assignment yields a value: to know whether a new value is set, assign and then check, 'x := f()' then 'ok <- x?'. A coalescing operator mixed with another binary operator must be parenthesised (E08269).
See Q79 for ':=?', Q1091 for '?:', Q939 for the comparison coalescing operators and Q1980 for the head forms.
Example
defines module qa.operators.questionmarknames defines function textOf() -> text as String <- rtn as String: text countOf() -> count as Integer <- rtn as Integer: count defines program QuestionMarkNames() stdout <- Stdout() maybe <- textOf(String()) //set-check: x? stdout.println(`set-check: maybe? is ${maybe?}`) //declaration guard: <- in a head if guarded <- textOf("guarded") stdout.println(`declaration guard entered with ${guarded}`) //assign-if-unset: :=? fills only an unset target maybe :=? "filled" stdout.println(`assign-if-unset: maybe is ${maybe}`) //assignment: := is blind, so check the new value with then x? entered <- false if maybe := textOf(String()) then maybe? entered: true stdout.println(`assignment re-pointed maybe: set is ${maybe?}, entered is ${entered}`) //coalesce (Elvis): the left if set, otherwise the right chosen <- maybe ?: "fallback" stdout.println(`coalesce: ${chosen}`) //comparison coalescing: returns an operand - the set one, or the lesser lower <- countOf(Integer()) <? countOf(7) stdout.println(`comparison coalescing: ${lower}`)
Common mistakes
E07340 — An assignment in a head is blind - it checks nothing - so the if has no condition. Add 'then maybe?' to enter only when the new value is set. See ek9 -h E07340 for details.
Incorrect:
if maybe := textOf(String())
Correct:
if maybe := textOf(String()) then maybe?
E08269 — '?:' binds tighter than '+', so this would be (maybe ?: "fallback") + "!". Parenthesise whichever is meant. See ek9 -h E08269 for details.
Incorrect:
chosen <- maybe ?: "fallback" + "!"
Correct:
chosen <- maybe ?: "fallback"
Other ways to ask this
- What is the difference between ':=?' and ':='?
- Is there a '?=' operator in EK9?
- What do I call ':=?' and '?:'?
- Which of EK9's operators check whether a value is set?
Coming from another language?
C#/JavaScript: '??=' is EK9's ':=?' and '??' is close to EK9's '?:' (EK9 also falls back for an UNSET value). Kotlin: '?:' is the same name and shape. Swift: 'if let' is EK9's declaration guard. Groovy's '?=' does not exist in EK9.
Keywords: :=?, <?, Elvis, assign-if-unset, names, <-, ?:, ?, :=, comparison coalescing, coalesce, declaration guard, set-check