How do I manage resources with try-with-resources in EK9?

← Error Handling and Exceptions · Ref: Q137

EK9 supports try-with-resources for automatic resource management. Resources declared in the try header are automatically closed when the scope exits, whether normally or via exception.

RESOURCE BINDING

Declare resources in the try header with the arrow syntax:

  try
    -> resource <- ResourceClass("config")
    useResource(resource)
  catch
    -> ex as Exception
    handleError(ex)

The resource is created before the try body and automatically closed after.

OPERATOR CLOSE

A resource class must define 'operator close' to support try-with-resources:

  ResourceClass
    name <- String()
    operator close as pure
      performCleanup()

The close operator is called automatically when the try scope exits.

RESOURCE WITH CATCH

Combine resources with error handling:

  try
    -> conn <- openConnection()
    data <- conn.read()
  catch
    -> ex as Exception
    handleError(ex)

The connection is closed whether read() succeeds or throws.

COMPARISON WITH OTHER LANGUAGES

Java: try (var r = new Resource()) { use(r); }
Python: with open(file) as f: use(f)
EK9: try -> resource <- Resource() ... (arrow syntax in try header)
All three guarantee cleanup. EK9's syntax is consistent with its guard variable pattern.

See Q134 for basic try/catch. See Q135 for try/catch/finally. See Q78 for guard variables in try blocks.

See Q333 for transaction try-with-resources pattern.

Example

defines module qa.errorhandling.trywithresources

  defines class

    <?-
      A simple resource that tracks open/close state.
    -?>
    ManagedResource
      name <- String()

      ManagedResource()
        -> name as String
        this.name: name

      name() as pure
        <- rtn as String: name

      read() as pure
        <- rtn as String: "data from " + name

      operator close as pure
        stdout <- Stdout()
        stdout.println("Closing: " + name)

      override operator ? as pure
        <- rtn <- true

  defines function

    openResource()
      -> name as String
      <- rtn <- ManagedResource(name)

  defines program

    TryWithResourcesDemo()
      stdout <- Stdout()

      // === BASIC TRY-WITH-RESOURCES ===

      stdout.println("=== Basic resource ===")
      try
        -> resource <- ManagedResource("config.txt")
        content <- resource.read()
        stdout.println("Read: " + content)
      catch
        -> ex as Exception
        stdout.println("Error: " + $ex)

      // === RESOURCE FROM FUNCTION ===

      stdout.println("=== Resource from function ===")
      try
        -> resource <- openResource("database")
        content <- resource.read()
        stdout.println("Read: " + content)
      catch
        -> ex as Exception
        stdout.println("Error: " + $ex)

      // === RESOURCE WITH NO EXCEPTION ===

      stdout.println("=== Clean exit ===")
      result <- String()
      try
        -> resource <- ManagedResource("temp.dat")
        result: resource.read()
      catch
        -> ex as Exception
        result: "error"

      stdout.println("Result: " + result)

Common mistakes

E07660 — Try-with-resources requires 'operator close', not a regular method named close. The name 'close' is reserved for the operator and cannot be used as a method name. See ek9 -h E07660 for details.

Incorrect:

close() as pure

Correct:

operator close as pure

E07620 — Try-with-resources requires the class to define 'operator close'. Without it, the type cannot be used as a resource in a try header. Renaming to a regular method removes the operator. See ek9 -h E07620 for details.

Incorrect:

cleanup() as pure

Correct:

operator close as pure

E50060 — ManagedResource has a read() method, not getData(). Check the class definition to confirm method names. See ek9 -h E50060 for details.

Incorrect:

content <- resource.getData()

Correct:

content <- resource.read()

E50060 — EK9 has no toString() method. Use string concatenation or interpolation. See ek9 -h E50060 for details.

Incorrect:

stdout.println(content.toString())

Correct:

stdout.println("Read: " + content)
Other ways to ask this
  • How does try-with-resources work in EK9?
  • How do I auto-close resources in EK9?
  • What is the EK9 equivalent of Python with statement?

Coming from another language?

Java: try (var r = new Resource()) { ... } with AutoCloseable interface. Python: with open(file) as f: ... with context manager protocol (__enter__/__exit__). Rust: no try-with-resources, RAII with Drop trait handles cleanup automatically. Go: defer file.Close() after opening. Kotlin: use { } extension on Closeable. EK9: try -> resource <- expr with 'operator close' for auto-cleanup, consistent with guard variable syntax.

Keywords: error, automatic, operator, catch, handle, dispose, manage, resource, close, RAII, try, auto, exception, cleanup, migrate