Defer statement

Instead of a try finally statement a defer statement can be used, which avoids lexical nesting and offers more flexibility in terms of scoping as shown below.

Any statements following the defer will be considered to be in an implicit try block in the current block:

  1. proc main =
  2. var f = open("numbers.txt", fmWrite)
  3. defer: close(f)
  4. f.write "abc"
  5. f.write "def"

Is rewritten to:

  1. proc main =
  2. var f = open("numbers.txt")
  3. try:
  4. f.write "abc"
  5. f.write "def"
  6. finally:
  7. close(f)

When defer is at the outermost scope of a template/macro, its scope extends to the block where the template/macro is called from:

  1. template safeOpenDefer(f, path) =
  2. var f = open(path, fmWrite)
  3. defer: close(f)
  4. template safeOpenFinally(f, path, body) =
  5. var f = open(path, fmWrite)
  6. try: body # without `defer`, `body` must be specified as parameter
  7. finally: close(f)
  8. block:
  9. safeOpenDefer(f, "/tmp/z01.txt")
  10. f.write "abc"
  11. block:
  12. safeOpenFinally(f, "/tmp/z01.txt"):
  13. f.write "abc" # adds a lexical scope
  14. block:
  15. var f = open("/tmp/z01.txt", fmWrite)
  16. try:
  17. f.write "abc" # adds a lexical scope
  18. finally: close(f)

Top-level defer statements are not supported since it’s unclear what such a statement should refer to.