diff --git a/Destructors,-2nd-edition.rest b/Destructors,-2nd-edition.rest index 5e65cee..0992c93 100644 --- a/Destructors,-2nd-edition.rest +++ b/Destructors,-2nd-edition.rest @@ -2,7 +2,6 @@ Nim Destructors and Move Semantics ================================== - .. contents:: @@ -395,6 +394,50 @@ Cursor variables are commonly used in ``iterator`` implementations: 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 ==========