Does 'if allowed <- permitted()' run its body when permitted() returns false?
← Control Flow · Ref: Q2001
No. A guard normally enters when its value is SET, but over a Boolean an 'if' (or 'else if') guard enters only when the value is SET AND TRUE. 'if allowed <- permitted(user)' skips the body for false just as it does for an unset result, so no trailing 'then allowed' is needed. The same holds for ':=?' in an if head: 'if decision :=? permitted(false)' fills decision with false and skips the body.
It is deliberately narrow:
- only 'if' and 'else if'; a 'switch' keeps enter-if-set, so its 'case false' stays reachable, and so do 'while', 'do', 'for' and 'try'
- only '<-' and ':=?'; a ':=' head is blind (E07340 without a condition)
- only a variable DECLARED Boolean; a type that merely promotes to Boolean keeps enter-if-set
An unset Boolean skips the body as any unset value does.
See Q74 for the guard in an if and Q1980 for the head forms side by side.
Example
defines module qa.controlflow.booleantruthguard defines function permitted() -> allowed as Boolean <- rtn as Boolean: allowed unknown() <- rtn as Boolean: Boolean() defines program BooleanTruthGuard() stdout <- Stdout() if granted <- permitted(true) stdout.println(`if over true: entered, granted=${granted}`) if refused <- permitted(false) stdout.println(`if over false: entered, refused=${refused}`) else stdout.println("if over false: skipped") if missing <- unknown() stdout.println(`if over unset: entered, missing=${missing}`) else stdout.println("if over unset: skipped") decision <- Boolean() if decision :=? permitted(false) stdout.println(`fill with false: entered, decision=${decision}`) else stdout.println(`fill with false: skipped, decision set=${decision?}`) switch answer <- permitted(false) case true stdout.println("switch over false: case true") case false stdout.println(`switch over false: case false, answer=${answer}`) default stdout.println("switch over false: default")
Common mistakes
E07340 — ':=' in a head is a blind assignment and checks nothing, so the if has no condition. Use ':=?' (which fills an unset target and, over a Boolean in an if, enters only when true) or add 'then decision'. See ek9 -h E07340 for details.
Incorrect:
if decision := permitted(false)
Correct:
if decision :=? permitted(false)
Other ways to ask this
- How does a guard behave when the value is a Boolean?
- Why is my if guard skipped when the Boolean is false?
- Does a switch guard over a Boolean still reach case false?
- Is 'then allowed' needed after 'if allowed <- check()'?
Coming from another language?
Swift: 'if let allowed = permitted()' enters for false (it only unwraps). Kotlin: 'permitted()?.let { }' enters for false. Java: 'if (Boolean.TRUE.equals(permitted()))' is the null-safe truth test. EK9: the guard over a Boolean is that null-safe truth test, in an if.
Keywords: truth, case false, else if, Boolean, guard, if, switch, declaration guard, assign-if-unset