Assign a value from a function only if it returns a set result, using a guard.

← Control Flow · Ref: Q1146

Guard with <- declares a variable AND checks isSet in one line:

  if userName <- findUser(1)
    stdout.println(`Found: ${userName}`)
  else
    stdout.println("User not found")
  //Same pattern works in switch, for, while, and try:
  while conn <- getConnection()
    process(conn)
  switch record <- database.lookup(id)
    case .type == "USER"
      handleUser(record)

If the right-hand side returns UNSET, the entire block is skipped. The variable only exists inside the guarded block.

See Q1038 for config defaults. See Q1152 for :=? guarded assignment.

Example

defines module qa.controlflow.ifguardassignment

  defines function

    findUser() as pure
      -> userId as Integer
      <- name as String: String()
      if userId == 1
        name: "Alice"

  defines program

    IfGuardAssignmentDemo()
      stdout <- Stdout()

      //Guard: block runs only if findUser returns set
      if userName <- findUser(1)
        stdout.println(`Found: ${userName}`)

      //Guard: unset result skips the block
      if userName2 <- findUser(999)
        stdout.println(`Found: ${userName2}`)
      else
        stdout.println("User not found")
Other ways to ask this
  • I need to execute a block only when a function returns a meaningful value
  • In Kotlin I'd use let { } for null-safe access. Write the EK9 guard equivalent
  • Given a function that might return unset, guard the result before using it
  • Use an if-guard to safely unwrap an optional result from a function call

Coming from another language?

Kotlin: getName()?.let { name -> println(name) }. Swift: if let name = getName(). EK9: if name <- getName().

Keywords: safe, <-, unset, assignment, if, unwrap, guard