std/wrapnils (original) (raw)
This module allows evaluating expressions safely against the following conditions:
- nil dereferences
- field accesses with incorrect discriminant in case objects
default(T) is returned in those cases when evaluating an expression of type T. This simplifies code by reducing need for if-else branches.
Note: experimental module, unstable API.
Example:
import std/wrapnils type Foo = ref object x1: string x2: Foo x3: ref int
var f: Foo assert ?.f.x2.x1 == ""
var f2 = Foo(x1: "a") f2.x2 = f2 assert ?.f2.x1 == "a" assert ?.Foo(x1: "a").x1 == "a"
assert ?.(f2.x2.x2).x3[] == 0
assert (?.f2.x2.x2).x3 == nil
Example:
import std/wrapnils
type B = object b0: int case cond: bool of false: discard of true: b1: float
var b = B(cond: false, b0: 3) doAssertRaises(FieldDefect): discard b.b1 doAssert ?.b.b1 == 0.0 b = B(cond: true, b1: 4.5) doAssert ?.b.b1 == 4.5
if (let p = ?.b.b1.addr; p != nil): p[] = 4.7 doAssert b.b1 == 4.7
Macros
Transforms a into an expression that can be safely evaluated even in presence of intermediate nil pointers/references, in which case a default value is produced.Source Edit
Same as ?. but returns an Option.
Example:
import std/options type Foo = ref object x1: ref int x2: int
var f1 = Foo(x1: int.new, x2: 2) doAssert (??.f1.x1[]).get == 0 doAssert (??.f1.x1[]).isSome doAssert (??.f1.x2).get == 2
var f2: Foo doAssert not (??.f2.x1[]).isSome
doAssertRaises(UnpackDefect): discard (??.f2.x1[]).get doAssert ?.f2.x1[] == 0