summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2020-11-16 23:40:17 -0800
committerGitHub <noreply@github.com>2020-11-17 08:40:17 +0100
commit50d035b7896b85184fc6e97e22f32a189d76b81b (patch)
treebd6e2eb89f809bd8270c25e39b39672519b4a5a9
parent61352d5a203e76e3334b21766bdbd4ebc71c300a (diff)
downloadNim-50d035b7896b85184fc6e97e22f32a189d76b81b.tar.gz
defer: improve manual, clarify difference wrt try/finally (#16010)
-rw-r--r--doc/manual.rst33
1 files changed, 31 insertions, 2 deletions
diff --git a/doc/manual.rst b/doc/manual.rst
index 9a4ae378d..1a23c5997 100644
--- a/doc/manual.rst
+++ b/doc/manual.rst
@@ -4414,7 +4414,9 @@ Custom exceptions can be raised like any others, e.g.:
 Defer statement
 ---------------
 
-Instead of a ``try finally`` statement a ``defer`` statement can be used.
+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`` in the current block will be considered
 to be in an implicit try block:
@@ -4423,7 +4425,7 @@ to be in an implicit try block:
     :test: "nim c $1"
 
   proc main =
-    var f = open("numbers.txt")
+    var f = open("numbers.txt", fmWrite)
     defer: close(f)
     f.write "abc"
     f.write "def"
@@ -4441,6 +4443,33 @@ Is rewritten to:
     finally:
       close(f)
 
+When `defer` is at the outermost scope of a template/macro, its scope extends
+to the block where the template is called from:
+
+.. code-block:: nim
+    :test: "nim c $1"
+
+  template safeOpenDefer(f, path) =
+    var f = open(path, fmWrite)
+    defer: close(f)
+
+  template safeOpenFinally(f, path, body) =
+    var f = open(path, fmWrite)
+    try: body # without `defer`, `body` must be specified as parameter
+    finally: close(f)
+
+  block:
+    safeOpenDefer(f, "/tmp/z01.txt")
+    f.write "abc"
+  block:
+    safeOpenFinally(f, "/tmp/z01.txt"):
+      f.write "abc" # adds a lexical scope
+  block:
+    var f = open("/tmp/z01.txt", fmWrite)
+    try:
+      f.write "abc" # adds a lexical scope
+    finally: close(f)
+
 Top-level ``defer`` statements are not supported
 since it's unclear what such a statement should refer to.