Skip to content

Commit

Permalink
nilwrap => wrapnil
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheecour committed Jan 5, 2020
1 parent a962d44 commit 0ddb569
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 26 deletions.
4 changes: 2 additions & 2 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
- Added `sugar.capture` for capturing some local loop variables when creating a closure.
This is an enhanced version of `closureScope`.

- Added `nilwraps.nilwrap` for chains of field-access and indexing where the LHS can be nil.
- Added `wrapnils.wrapnil` for chains of field-access and indexing where the LHS can be nil.
This simplifies code by reducing need for if-else branches around intermediate maybe nil values.
Eg: `echo n.nilwrap.typ.kind[]`
Eg: `echo n.wrapnil.typ.kind[]`

## Library changes

Expand Down
30 changes: 15 additions & 15 deletions lib/std/nilwraps.nim → lib/std/wrapnils.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
type Nilwrap*[T] = object
type Wrapnil*[T] = object
valueImpl*: T

proc nilwrap*[T](a: T): auto =
proc wrapnil*[T](a: T): auto =
## Allows chains of field-access and indexing where the LHS can be nil.
## This simplifies code by reducing need for if-else branches around intermediate
## maybe nil values.
Expand All @@ -10,32 +10,32 @@ proc nilwrap*[T](a: T): auto =
x1: string
x2: Foo
var f: Foo
assert f.nilwrap.x2.x1[] == ""
Nilwrap[T](valueImpl: a)
assert f.wrapnil.x2.x1[] == ""
Wrapnil[T](valueImpl: a)

{.push experimental: "dotOperators".}

template `.`*(a: Nilwrap, b): untyped =
## See `nilwrap`
template `.`*(a: Wrapnil, b): untyped =
## See `wrapnil`
let a2 = a.valueImpl # to avoid double evaluations
when type(a2) is ref|ptr:
if a2 == nil:
nilwrap(default(type(a2.b)))
wrapnil(default(type(a2.b)))
else:
nilwrap(a2.b)
wrapnil(a2.b)
else:
nilwrap(a2.b)
wrapnil(a2.b)

{.pop.}

template `[]`*(a: Nilwrap): untyped =
## See `nilwrap`
template `[]`*(a: Wrapnil): untyped =
## See `wrapnil`
a.valueImpl

template `[]`*[I](a: Nilwrap, i: I): untyped =
## See `nilwrap`
template `[]`*[I](a: Wrapnil, i: I): untyped =
## See `wrapnil`
let a2 = a.valueImpl # to avoid double evaluations
if len(a2) == 0:
nilwrap(default(type(a2[i])))
wrapnil(default(type(a2[i])))
else:
nilwrap(a2[i])
wrapnil(a2[i])
18 changes: 9 additions & 9 deletions tests/stdlib/tnilwraps.nim → tests/stdlib/twrapnils.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import std/nilwraps
import std/wrapnils

proc main() =
type Bar = object
Expand All @@ -20,17 +20,17 @@ proc main() =
witness.inc
result = Foo(x1: x1)

doAssert a.nilwrap.x2.x2.x1[] == 0.0
doAssert a3.nilwrap.x2.x2.x1[] == 1.2
doAssert a3.nilwrap.x2.x2.x5.len[] == 0
doAssert a3.nilwrap.x2.x2.x3.len[] == 3
doAssert a3.nilwrap.x2.x2.x3.len == nilwrap(3)
doAssert a3.nilwrap.x2.x2.x3[1][] == 'b'
doAssert a.nilwrap.x2.x2.x3[1][] == default(char)
doAssert a.wrapnil.x2.x2.x1[] == 0.0
doAssert a3.wrapnil.x2.x2.x1[] == 1.2
doAssert a3.wrapnil.x2.x2.x5.len[] == 0
doAssert a3.wrapnil.x2.x2.x3.len[] == 3
doAssert a3.wrapnil.x2.x2.x3.len == wrapnil(3)
doAssert a3.wrapnil.x2.x2.x3[1][] == 'b'
doAssert a.wrapnil.x2.x2.x3[1][] == default(char)

# make sure no double evaluation bug
doAssert witness == 0
doAssert initFoo(1.3).nilwrap.x1[] == 1.3
doAssert initFoo(1.3).wrapnil.x1[] == 1.3
doAssert witness == 1

main()

0 comments on commit 0ddb569

Please sign in to comment.