Can guards be used in switch and while, not just if?

← Control Flow · Ref: Q975

Yes. The same 'v <- expression' guard works in if, switch, while and try: it means 'declare v, check if SET, only proceed if SET'. One difference to know: in a loop the guard is evaluated ONCE, on entry (if it is unset the body is skipped); only the 'with' condition is re-tested on every iteration.

IN IF:

  if name <- findUser(id)
    stdout.println(name)

IN SWITCH:

  switch kind <- database.kindOf(id) with kind
    case == "USER"
      processUser(kind)
    default
      processOther(kind)

IN WHILE (the guard runs once; 'with' is the per-iteration test):

  while conn <- openConnection() with counter < maxIters
    process(conn)
    counter: counter + 1

IN TRY:

  try connection <- openDatabase()
    query(connection)
  catch
    -> ex as Exception
    logError(ex)

The guard syntax is the same everywhere - one syntax to learn. This eliminates 90-95% of null pointer exceptions across ALL control flow.

See Q971 for if guard details. See Q75 for switch guard details.

Example

defines module qa.controlflow.guardcontexts

  defines function

    <?-
      Returns a set or unset value based on input.
    -?>
    fetchValue() as pure
      -> key as String
      <- rtn as String: String()

      if key?
        rtn: "Value for " + key

  defines program

    GuardContextsDemo()
      stdout <- Stdout()

      // Guard in IF
      if greeting <- fetchValue("hello")
        stdout.println(`IF guard: ${greeting}`)

      // Guard in IF with else
      if missing <- fetchValue(String())
        stdout.println(missing)
      else
        stdout.println("IF guard: skipped because unset")

      // Guard in SWITCH
      switch found <- fetchValue("test") with found
        case == "Value for test"
          stdout.println(`SWITCH guard: exact match`)
        default
          stdout.println(`SWITCH guard: ${found}`)

Common mistakes

E01073 — 'null' does not exist in EK9; check a value with the '?' isSet operator, not '!= null'. See ek9 -h E01073 for details.

Incorrect:

if key != null

Correct:

if key?
Other ways to ask this
  • Where can I use the <- guard pattern in EK9?
  • Does the declaration guard work in switch statements?
  • Show me guards in while loops in EK9
  • Is the if v <- expr guard universal across EK9 control flow?
  • Can I use guards in switch statements and while loops, not just if?
  • Show me guards in a switch statement in EK9
  • How do guards work in while loops in EK9?
  • Do EK9 guards work in all control flow constructs?

Coming from another language?

Go: if err := f(); err != nil — only works in if. Rust: if let — only works in if/while. Swift: if let — only in if. EK9: the same guard syntax works in if, switch, while, and try (in a loop the guard is evaluated once, 'with' is re-tested).

Keywords: universal, try, try guard, while, switch guard, guard, switch, while guard, control flow