From 4cea3467cb2347731d226e8d3ecee6a85b72d3ff Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Thu, 6 Jun 2019 08:08:20 +0200 Subject: [PATCH] Updated Destructors, 2nd edition (rest) --- Destructors,-2nd-edition.rest | 45 ++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) 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 ==========