heterogenous or

Useful for translating `error` results
This commit is contained in:
Jacek Sieka 2020-05-08 12:16:07 +02:00 committed by zah
parent 638e7acc8e
commit 2d9226464d
2 changed files with 31 additions and 7 deletions

View File

@ -372,16 +372,30 @@ template `and`*[T0, E, T1](self: Result[T0, E], other: Result[T1, E]): Result[T1
let s = self let s = self
if s.o: if s.o:
other other
else:
when type(self) is type(other):
s
else: else:
type R = type(other) type R = type(other)
R.err(s.e) 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

View File

@ -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