results: Add `isOkOr`, `isErrOr` (#176)
These two helpers complete `valueOr` and `errorOr` to cover `void` cases where no value should be returned or `Result[void, E]` / `Result[T, void]` is being used - they can be used for a convient early-return style in side-effectful proc:s: ```nim v.update().isOkOr: echo "update failed: ", error ```
This commit is contained in:
parent
67fdc87e25
commit
9b985e8ea8
|
@ -849,11 +849,67 @@ template unsafeError*[T](self: Result[T, void]) =
|
|||
template value*[T, E](self: Result[T, E]): T = self.get()
|
||||
template value*[T: not void, E](self: var Result[T, E]): var T = self.get()
|
||||
|
||||
template isOkOr*[T, E](self: Result[T, E], body: untyped) =
|
||||
## Evaluate `body` iff result has been assigned an error
|
||||
## `body` is evaluated lazily.
|
||||
##
|
||||
## Example:
|
||||
## ```
|
||||
## let
|
||||
## v = Result[int, string].err("hello")
|
||||
## x = v.isOkOr: echo "not ok"
|
||||
## # experimental: direct error access using an unqualified `error` symbol
|
||||
## z = v.isOkOr: echo error
|
||||
## ```
|
||||
##
|
||||
## `error` access:
|
||||
##
|
||||
## TODO experimental, might change in the future
|
||||
##
|
||||
## The template contains a shortcut for accessing the error of the result,
|
||||
## it can only be used outside of generic code,
|
||||
## see https://github.com/status-im/nim-stew/issues/161#issuecomment-1397121386
|
||||
|
||||
let s = (self) # TODO avoid copy
|
||||
if not s.oResultPrivate:
|
||||
when E isnot void:
|
||||
template error: E {.used, inject.} = s.eResultPrivate
|
||||
body
|
||||
|
||||
template isErrOr*[T, E](self: Result[T, E], body: untyped) =
|
||||
## Evaluate `body` iff result has been assigned a value
|
||||
## `body` is evaluated lazily.
|
||||
##
|
||||
## Example:
|
||||
## ```
|
||||
## let
|
||||
## v = Result[int, string].err("hello")
|
||||
## x = v.isOkOr: echo "not ok"
|
||||
## # experimental: direct error access using an unqualified `error` symbol
|
||||
## z = v.isOkOr: echo error
|
||||
## ```
|
||||
##
|
||||
## `value` access:
|
||||
##
|
||||
## TODO experimental, might change in the future
|
||||
##
|
||||
## The template contains a shortcut for accessing the value of the result,
|
||||
## it can only be used outside of generic code,
|
||||
## see https://github.com/status-im/nim-stew/issues/161#issuecomment-1397121386
|
||||
|
||||
let s = (self) # TODO avoid copy
|
||||
if s.oResultPrivate:
|
||||
when T isnot void:
|
||||
template value: T {.used, inject.} = s.vResultPrivate
|
||||
body
|
||||
|
||||
template valueOr*[T: not void, E](self: Result[T, E], def: untyped): T =
|
||||
## Fetch value of result if set, or evaluate `def`
|
||||
## `def` is evaluated lazily, and must be an expression of `T` or exit
|
||||
## the scope (for example using `return` / `raise`)
|
||||
##
|
||||
## See `isOkOr` for a version that works with `Result[void, E]`.
|
||||
##
|
||||
## Example:
|
||||
## ```
|
||||
## let
|
||||
|
@ -869,11 +925,12 @@ template valueOr*[T: not void, E](self: Result[T, E], def: untyped): T =
|
|||
## TODO experimental, might change in the future
|
||||
##
|
||||
## The template contains a shortcut for accessing the error of the result,
|
||||
## without specifying the error - it can only be used outside of generic code,
|
||||
## it can only be used outside of generic code,
|
||||
## see https://github.com/status-im/nim-stew/issues/161#issuecomment-1397121386
|
||||
##
|
||||
let s = (self) # TODO avoid copy
|
||||
if s.oResultPrivate: s.vResultPrivate
|
||||
if s.oResultPrivate:
|
||||
s.vResultPrivate
|
||||
else:
|
||||
when E isnot void:
|
||||
template error: E {.used, inject.} = s.eResultPrivate
|
||||
|
@ -883,8 +940,11 @@ template errorOr*[T, E: not void](self: Result[T, E], def: untyped): E =
|
|||
## Fetch error of result if not set, or evaluate `def`
|
||||
## `def` is evaluated lazily, and must be an expression of `T` or exit
|
||||
## the scope (for example using `return` / `raise`)
|
||||
##
|
||||
## See `isErrOr` for a version that works with `Result[T, void]`.
|
||||
let s = (self) # TODO avoid copy
|
||||
if not s.oResultPrivate: s.eResultPrivate
|
||||
if not s.oResultPrivate:
|
||||
s.eResultPrivate
|
||||
else:
|
||||
when T isnot void:
|
||||
template value: T {.used, inject.} = s.vResultPrivate
|
||||
|
|
|
@ -70,6 +70,15 @@ block:
|
|||
|
||||
doAssert rOk.get() == rOk.unsafeGet()
|
||||
|
||||
rOk.isOkOr: raiseAssert "should not end up in here"
|
||||
rErr.isErrOr: raiseAssert "should not end up in here"
|
||||
|
||||
rErr.isOkOr:
|
||||
doAssert error == rErr.error()
|
||||
|
||||
rOk.isErrOr:
|
||||
doAssert value == rOk.value()
|
||||
|
||||
doAssert rOk.valueOr(failFast()) == rOk.value()
|
||||
let rErrV = rErr.valueOr:
|
||||
error.len
|
||||
|
|
Loading…
Reference in New Issue