Defer in Nim

import os

# Defer is used to ensure that a function call is performed later in a program's
# execution, usually for purposes of cleanup. In Nim, we use the `defer` statement
# which is similar to `try`/`finally` in other languages.

proc createFile(p: string): File =
  echo "creating"
  result = open(p, fmWrite)
  if result == nil:
    raise newException(IOError, "Failed to create file")

proc writeFile(f: File) =
  echo "writing"
  f.writeLine("data")

proc closeFile(f: File) =
  echo "closing"
  try:
    f.close()
  except IOError:
    stderr.writeLine("error: ", getCurrentExceptionMsg())
    quit(1)

proc main() =
  # Suppose we wanted to create a file, write to it,
  # and then close when we're done. Here's how we could
  # do that with `defer`.

  # Immediately after getting a file object with
  # `createFile`, we defer the closing of that file
  # with `closeFile`. This will be executed at the end
  # of the enclosing block, after `writeFile` has finished.
  let f = createFile("/tmp/defer.txt")
  defer: closeFile(f)
  writeFile(f)

# Running the program
main()

Running the program confirms that the file is closed after being written:

$ nim c -r defer.nim
creating
writing
closing

In Nim, we use the defer statement to achieve similar functionality to Go’s defer. The defer statement in Nim ensures that the specified code block is executed when the current scope is exited, whether normally or due to an exception.

The main differences in this Nim version compared to the original are:

  1. We use Nim’s File type instead of *os.File.
  2. Error handling is done using exceptions rather than returning error values.
  3. The defer statement is used within the main procedure, which is similar to Go’s usage.
  4. We use newException to create and raise exceptions in Nim.
  5. The quit procedure is used instead of os.Exit to terminate the program with an error code.

This example demonstrates how to use defer in Nim for resource cleanup, ensuring that files are properly closed even if an error occurs during writing.