mirror of
https://github.com/status-im/nim-stew.git
synced 2025-01-09 03:22:17 +00:00
heterogenous or
Useful for translating `error` results
This commit is contained in:
parent
638e7acc8e
commit
2d9226464d
@ -373,15 +373,29 @@ template `and`*[T0, E, T1](self: Result[T0, E], other: Result[T1, E]): Result[T1
|
|||||||
if s.o:
|
if s.o:
|
||||||
other
|
other
|
||||||
else:
|
else:
|
||||||
type R = type(other)
|
when type(self) is type(other):
|
||||||
R.err(s.e)
|
s
|
||||||
|
else:
|
||||||
|
type R = type(other)
|
||||||
|
err(R, s.e)
|
||||||
|
|
||||||
template `or`*[T, E](self, other: Result[T, E]): Result[T, E] =
|
template `or`*[T, E0, E1](self: Result[T, E0], other: Result[T, E1]): Result[T, E1] =
|
||||||
## Evaluate `other` iff not self.isOk, else return self
|
## Evaluate `other` iff `not self.isOk`, else return `self`
|
||||||
## fail-fast - will not evaluate other if a is a value
|
## fail-fast - will not evaluate `other` if `self` is ok
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## func f(): Result[int, SomeEnum] =
|
||||||
|
## f2() or err(EnumValue) # Collapse errors from other module / function
|
||||||
|
## ```
|
||||||
let s = self
|
let s = self
|
||||||
if s.o: s
|
if s.o:
|
||||||
else: other
|
when type(self) is type(other):
|
||||||
|
s
|
||||||
|
else:
|
||||||
|
type R = type(other)
|
||||||
|
ok(R, s.v)
|
||||||
|
else:
|
||||||
|
other
|
||||||
|
|
||||||
template catch*(body: typed): Result[type(body), ref CatchableError] =
|
template catch*(body: typed): Result[type(body), ref CatchableError] =
|
||||||
## Catch exceptions for body and store them in the Result
|
## Catch exceptions for body and store them in the Result
|
||||||
|
@ -35,6 +35,9 @@ doAssert (rErr or rOk).isOk
|
|||||||
# `and` heterogenous types
|
# `and` heterogenous types
|
||||||
doAssert (rOk and rOk.map(proc(x: auto): auto = $x))[] == $(rOk[])
|
doAssert (rOk and rOk.map(proc(x: auto): auto = $x))[] == $(rOk[])
|
||||||
|
|
||||||
|
# `or` heterogenous types
|
||||||
|
doAssert (rErr or rErr.mapErr(proc(x: auto): auto = len(x))).error == len(rErr.error)
|
||||||
|
|
||||||
# Exception on access
|
# Exception on access
|
||||||
let va = try: discard rOk.error; false except: true
|
let va = try: discard rOk.error; false except: true
|
||||||
doAssert va, "not an error, should raise"
|
doAssert va, "not an error, should raise"
|
||||||
@ -182,6 +185,13 @@ doAssert testQn()[] == 0
|
|||||||
doAssert testQn2().isErr
|
doAssert testQn2().isErr
|
||||||
doAssert testQn3()[]
|
doAssert testQn3()[]
|
||||||
|
|
||||||
|
proc heterOr(): Result[int, int] =
|
||||||
|
let value = ?(rErr or err(42)) # TODO ? binds more tightly than `or` - can that be fixed?
|
||||||
|
doAssert value + 1 == value, "won't reach, ? will shortcut execution"
|
||||||
|
ok(value)
|
||||||
|
|
||||||
|
doAssert heterOr().error() == 42
|
||||||
|
|
||||||
type
|
type
|
||||||
AnEnum = enum
|
AnEnum = enum
|
||||||
anEnumA
|
anEnumA
|
||||||
|
Loading…
x
Reference in New Issue
Block a user