How do I declare a variable inside an if condition in EK9?

← Control Flow · Ref: Q973

Use the guard pattern: 'if v <- expression'. This declares v AND checks if it is SET. The block only runs if the value is set.

SYNTAX:

  if variableName <- someExpression()
    // only runs if someExpression() returned a SET value
    // variableName is available here

The <- inside an if is a GUARD DECLARATION. It combines:
1. Declare a new variable
2. Call the expression
3. Check if the result is SET (not unset/absent)
4. Only enter the block if SET

WITH ADDITIONAL CONDITION:

  if v <- getValue() then v > 0
    // runs if getValue() is SET AND v > 0

WITH ELSE:

  if result <- compute()
    stdout.println(result)
  else
    stdout.println("compute returned unset")

This replaces null checks in other languages:

  Java:   if (x != null) { use(x); }
  Kotlin: x?.let { use(it) }
  Rust:   if let Some(x) = expr { use(x); }
  EK9:    if x <- expr()
            use(x)

See Q74 for more guard patterns. See Q971 for guard details.

Example

defines module qa.controlflow.guarddeclaration

  defines function

    <?-
      May return a set or unset String.
    -?>
    lookupUser() as pure
      -> userId as Integer
      <- rtn as String: String()

      if userId > 0
        rtn: `User-${userId}`

  defines program

    GuardDeclarationDemo()
      stdout <- Stdout()

      // Guard: declares 'user' and only enters if SET
      if user <- lookupUser(1)
        stdout.println(`Found: ${user}`)

      // Guard with unset result: else branch runs
      if user <- lookupUser(0)
        stdout.println("Should not print")
      else
        stdout.println("User not found - guard skipped block")

      // Guard with additional condition
      minId <- 1
      if user <- lookupUser(5) then user.length() > minId
        stdout.println(`Valid user: ${user}`)

Common mistakes

E01073 — 'null' does not exist in EK9 — return the tri-state unset value String() instead of a null literal. See ek9 -h E01073 for details.

Incorrect:

      <- rtn as String: null

Correct:

      <- rtn as String: String()
Other ways to ask this
  • What is the if v <- expr pattern in EK9?
  • How do guards combine declaration and null checking in EK9?
  • How do I skip a block when a value is unset in EK9?

Coming from another language?

Go: if err := f(); err != nil. Rust: if let Some(v) = expr. Swift: if let v = optional. Kotlin: val v = expr; if (v != null). EK9: if v <- expr() — one line, compile-time enforced.

Keywords: guard, null safety, if declaration, isSet check, control flow