1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
# Inspired by nim-results.
type
Result*[T, E] = object
when E is void and T is void: # weirdness
has*: bool
elif E is void and not (T is void): # opt
case has*: bool
of true:
val*: T
else:
discard
elif not (E is void) and T is void: # err
case has*: bool
of true:
discard
else:
ex*: E
else: # result
case has*: bool
of true:
val*: T
else:
ex*: E
Opt*[T] = Result[T, void]
Err*[E] = Result[void, E]
template ok*[E](t: type Err[E]): Err[E] =
Err[E](has: true)
template ok*[T, E](t: type Result[T, E], x: T): Result[T, E] =
Result[T, E](val: x, has: true)
template ok*[T](x: T): auto =
ok(typeof(result), x)
template ok*(): auto =
ok(typeof(result))
template ok*[T, E](res: var Result[T, E], x: T) =
res = Result[T, E](has: true, val: x)
template ok*[E](res: var Result[void, E]) =
res = Result[void, E](has: true)
template err*[T, E](t: type Result[T, E], e: E): Result[T, E] =
Result[T, E](has: false, ex: e)
template err*[T](t: type Result[T, void]): Result[T, void] =
Result[T, void](has: false)
template err*(): auto =
err(typeof(result))
template err*[T, E](res: var Result[T, E], e: E) =
res = Result[T, E](has: false, ex: e)
template err*[T, E](res: var Result[T, E]) =
res = Result[T, E](has: false)
template err*[E](e: E): auto =
err(typeof(result), e)
template opt*[T](v: T): auto =
ok(Opt[T], v)
template opt*(t: typedesc): auto =
err(Result[t, void])
template opt*[T, E: not void](r: Result[T, E]): Opt[T] =
if r.isOk:
Opt[T].ok(r.get)
else:
Opt[T].err()
template isOk*(res: Result): bool = res.has
template isErr*(res: Result): bool = not res.has
template isSome*(res: Result): bool = res.isOk
template isNone*(res: Result): bool = res.isErr
func get*[T, E](res: Result[T, E]): T {.inline.} = res.val
func get*[T, E](res: var Result[T, E]): var T = res.val
func get*[T, E](res: Result[T, E], v: T): T =
if res.has:
res.val
else:
v
func error*[T, E](res: Result[T, E]): E {.inline.} = res.ex
template valType*[T, E](res: type Result[T, E]): auto = T
template errType*[T, E](res: type Result[T, E]): auto = E
template `?`*[T, E](res: Result[T, E]): auto =
let x = res # for when res is a funcall
if x.has:
when not (T is void):
x.get
else:
discard
else:
when typeof(result) is Result[T, E]:
return x
elif not (E is void) and typeof(result).errType is E:
return err(x.error)
else:
return err()
|