References, Pointers and the Heap
12.1 ref (Managed References)
ref objects are managed by ARC/ORC: freed deterministically when the last reference goes away (cycles are collected by ORC).
Dereference with []: head[] gives the underlying object.
nil dereference raises NilAccessDefect (or a segfault in danger mode).
type
Node = ref object
value: int
next: Node
# or: NodeObj = object ...; Node = ref NodeObj
var head = Node(value: 1)
head.next = Node(value: 2)
var alias = head # both point to the same object (reference semantics)
alias.value = 99
echo head.value # 99
if head.next.next == nil: echo "end of list"
let n = new(Node) # also allocates12.2 ptr (Unmanaged Pointers)
alloc, alloc0, realloc, dealloc, plus the createShared / allocShared variants for threads.
ptr is unsafe. Use it for FFI and low-level code.
var x = 10
let p: ptr int = addr x
p[] = 20
echo x # 20
let mem = cast[ptr UncheckedArray[int]](alloc0(10 * sizeof(int)))
mem[3] = 42
dealloc(mem)12.3 Value vs Reference Semantics Summary
int, float, object, tuple, array Stack (or inline) Value (copy, or move when possible) Heap buffer, managed Reference (shared) Reference (raw)
12.4 Nil Safety
The experimental --experimental:strictNotNil and not nil annotations: type SafeNode = ref NodeObj not nil.
Option[T] (std/options) for optional values:
import std/options
proc findUser(id: int): Option[string] =
if id == 1: some("Ana") else: none(string)
let u = findUser(2)
if u.isSome: echo u.get
echo u.get("anonymous") # default value