Updated Destructors, 2nd edition (rest)

This commit is contained in:
Andreas Rumpf 2019-06-06 08:08:20 +02:00
parent bba61c0452
commit 4cea3467cb
1 changed files with 44 additions and 1 deletions

View File

@ -2,7 +2,6 @@
Nim Destructors and Move Semantics Nim Destructors and Move Semantics
================================== ==================================
.. contents:: .. contents::
@ -395,6 +394,50 @@ Cursor variables are commonly used in ``iterator`` implementations:
yield it yield it
Lent type
=========
``proc p(x: sink T)`` means that the proc ``p`` takes ownership of ``x``.
To eliminate even more creation/copy <-> destruction pairs, a proc's return
type can be annotated as ``lent T``. This is useful for "getter" accessors
that seek to allow an immutable view into a container.
The ``sink`` and ``lent`` annotations allow us to remove most (if not all)
superfluous copies and destructions.
``lent T`` is like ``var T`` a hidden pointer. It is proven by the compiler
that the pointer does not outlive its origin. No destructor call is injected
for expressions of type ``lent T`` or of type ``var T``.
.. code-block:: nim
type
Tree = object
kids: seq[Tree]
proc construct(kids: sink seq[Tree]): Tree =
result = Tree(kids: kids)
# converted into:
`=sink`(result.kids, kids)
proc `[]`*(x: Tree; i: int): lent Tree =
result = x.kids[i]
# borrows from 'x', this is transformed into:
result = addr x.kids[i]
# This means 'lent' is like 'var T' a hidden pointer.
# Unlike 'var' this cannot be used to mutate the object.
iterator children*(t: Tree): lent Tree =
for x in t.kids: yield x
proc main =
# everything turned into moves:
let t = construct(@[construct(@[]), construct(@[])])
echo t[0] # accessor does not copy the element!
Owned refs Owned refs
========== ==========