defer: improve manual, clarify difference wrt try/finally (#16010)

(cherry picked from commit 50d035b789)
This commit is contained in:
Timothee Cour
2020-11-16 23:40:17 -08:00
committed by narimiran
parent cc6497406f
commit ce1570a6fb

View File

@@ -4372,7 +4372,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:
@@ -4381,7 +4383,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"
@@ -4399,6 +4401,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.