How do try/catch/finally work in EK9?

← Control Flow · Ref: Q902

EK9 has try/catch/finally similar to Java, but the catch clause uses '->' for the exception parameter — like Go's 'in' parameter or Ada's 'in' port.

BASIC TRY/CATCH

  try
    riskyOperation()
  catch
    -> ex as Exception
    stdout.println(`Error: ${ex}`)      the -> means 'data coming in'

IMPORTANT: The catch uses '->' on its own line, like function parameters. The exception is data flowing IN to the catch handler.

TRY/CATCH/FINALLY

  try
    openConnection()
    sendRequest()
  catch
    -> ex as Exception
    logError(ex)
  finally
    closeConnection()    always runs, like Java's finally

TRY AS EXPRESSION

Like switch, try can be an expression. It needs a returning variable that the body (and the catch) assign:

  result <- try
    <- rtn as String: "default value"
    rtn: parseInput(rawText)
  catch
    -> ex as Exception
    rtn: "recovered"

GUARD TRY

Try can use a guard variable:

  try result <- riskyComputation()
    stdout.println(result)
  catch
    -> ex as Exception
    stdout.println(`Failed: ${ex}`)

EXCEPTION TYPES

Exception is the base type and is declared 'as open', so you can extend it with your own exception types.
Use '$' on an exception to get its type and reason as a String ('Exception: <reason>'); ex.reason() gives just the reason text.

NO CHECKED EXCEPTIONS

EK9 does not have checked exceptions. All exceptions are runtime.

See Q130 for control flow. See Q893 for section headers.

Example

#!ek9
defines module qa.controlflow.trycatch

  defines function

    <?-
      Basic function that may throw.
    -?>
    safeDivide() as pure
      ->
        numerator as Integer
        denominator as Integer
      <-
        rtn as Float: #^ numerator / #^ denominator

  defines program

    TryCatchDemo()
      stdout <- Stdout()

      // Basic try/catch — note -> on catch for exception parameter
      // Like Go/Ada: -> means 'data flowing in' to the handler
      try
        quotient <- safeDivide(10, 2)
        stdout.println(`10 / 2 = ${quotient}`)
      catch
        -> ex as Exception
        stdout.println(ex.reason())

      // Try/catch/finally — finally always runs
      try
        result <- safeDivide(100, 4)
        stdout.println(`100 / 4 = ${result}`)
      catch
        -> ex as Exception
        stdout.println(ex.reason())
      finally
        stdout.println("Division complete")

      // Nested try/catch: the inner try sits inside the outer try body
      try
        firstResult <- safeDivide(20, 5)
        stdout.println(`20 / 5 = ${firstResult}`)
        try
          secondResult <- safeDivide(8, 2)
          stdout.println(`inner: ${secondResult}`)
        catch
          -> ex as Exception
          stdout.println(ex.reason())
      catch
        -> ex as Exception
        stdout.println(ex.reason())

      // Try as an expression: the returning variable carries the value
      parsed <- try
        <- rtn as String: "default value"
        rtn: `${safeDivide(9, 3)}`
      catch
        -> ex as Exception
        rtn: `failed: ${ex.reason()}`
      stdout.println(`parsed: ${parsed}`)

Common mistakes

E04030 — The catch clause requires an Exception type, not String or other types. The variable after -> must be declared 'as Exception'. See ek9 -h E04030 for details.

Incorrect:

      catch
        -> ex as String
        stdout.println(ex)
      finally

Correct:

      catch
        -> ex as Exception
        stdout.println(ex.reason())
      finally
Other ways to ask this
  • How do I catch exceptions in EK9?
  • What is the catch syntax in EK9?
  • Does EK9 have try/catch?
  • How do I handle exceptions in EK9?

Coming from another language?

Java: catch (Exception e) { ... } — EK9 uses -> ex as Exception on separate line. Go: if err != nil — EK9 has try/catch, not error values. Python: except Exception as e: — similar but EK9 uses -> prefix. Kotlin: catch (e: Exception) — EK9 uses -> for incoming data. Rust: Result and ? operator — EK9 has both try/catch and Result type. EK9: catch with -> ex as Exception — the -> means 'data flowing in' like Go/Ada parameter ports.

Keywords: arrow, catch, data-in, error, exception, finally, handle, throw, try