mirror of
https://github.com/logos-storage/questionable.git
synced 2026-01-02 13:53:11 +00:00
Without statement for Results provides access to errors
This commit is contained in:
parent
91a38040ea
commit
ef29000f94
14
Readme.md
14
Readme.md
@ -194,6 +194,20 @@ let value = fails() |? @[]
|
||||
let sum = works()[3] + 40
|
||||
```
|
||||
|
||||
### Without statement
|
||||
|
||||
The `without` statement can also be used with Results. It provides access to any
|
||||
errors that may arise:
|
||||
|
||||
```nim
|
||||
proc someProc(r: ?!int) =
|
||||
without value =? r, error:
|
||||
# use `error` to get the error from r
|
||||
return
|
||||
|
||||
# use value
|
||||
```
|
||||
|
||||
### Catching errors
|
||||
|
||||
When you want to use Results, but need to call a proc that may raise an
|
||||
|
||||
@ -6,6 +6,7 @@ import ./chaining
|
||||
import ./indexing
|
||||
import ./operators
|
||||
import ./without
|
||||
import ./withoutresult
|
||||
|
||||
include ./errorban
|
||||
|
||||
@ -14,6 +15,7 @@ export binding
|
||||
export chaining
|
||||
export indexing
|
||||
export without
|
||||
export withoutresult
|
||||
|
||||
type ResultFailure* = object of CatchableError
|
||||
|
||||
|
||||
22
questionable/withoutresult.nim
Normal file
22
questionable/withoutresult.nim
Normal file
@ -0,0 +1,22 @@
|
||||
import ./binding
|
||||
import ./without
|
||||
|
||||
template without*(expression, errorname, body) =
|
||||
## Used to place guards that ensure that a Result contains a value.
|
||||
## Exposes error when Result does not contain a value.
|
||||
|
||||
var error: ref CatchableError
|
||||
|
||||
# override =? operator such that it stores the error if there is one
|
||||
template `=?`(name, result): bool =
|
||||
when result is Result:
|
||||
if result.isFailure:
|
||||
error = result.error
|
||||
when result is Option:
|
||||
if result.isNone:
|
||||
error = newException(ValueError, "Option is set to `none`")
|
||||
binding.`=?`(name, result)
|
||||
|
||||
without expression:
|
||||
template errorname: ref CatchableError = error
|
||||
body
|
||||
@ -180,6 +180,69 @@ suite "result":
|
||||
test1()
|
||||
test2()
|
||||
|
||||
test "without statement can expose error":
|
||||
proc test =
|
||||
without a =? int.failure "some error", error:
|
||||
check error.msg == "some error"
|
||||
return
|
||||
fail
|
||||
|
||||
test()
|
||||
|
||||
test "without statement only exposes error variable inside block":
|
||||
proc test =
|
||||
without a =? 42.success, errorvar:
|
||||
fail
|
||||
discard errorvar # fixes warning about unused variable "errorvar"
|
||||
return
|
||||
check not compiles errorvar
|
||||
|
||||
test()
|
||||
|
||||
test "without statements with multiple bindings exposes first error":
|
||||
proc test1 =
|
||||
without (a =? int.failure "error 1") and
|
||||
(b =? int.failure "error 2"),
|
||||
error:
|
||||
check error.msg == "error 1"
|
||||
return
|
||||
fail
|
||||
|
||||
proc test2 =
|
||||
without (a =? 42.success) and (b =? int.failure "error 2"), error:
|
||||
check error.msg == "error 2"
|
||||
return
|
||||
fail
|
||||
|
||||
test1()
|
||||
test2()
|
||||
|
||||
test "without statement with error evaluates result only once":
|
||||
proc test =
|
||||
var count = 0
|
||||
without a =? (inc count; int.failure "error"):
|
||||
check count == 1
|
||||
return
|
||||
fail
|
||||
|
||||
test()
|
||||
|
||||
test "without statement with error handles options as well":
|
||||
proc test1 =
|
||||
without a =? int.none and b =? int.failure "error", error:
|
||||
check error.msg == "Option is set to `none`"
|
||||
return
|
||||
fail
|
||||
|
||||
proc test2 =
|
||||
without a =? 42.some and b =? int.failure "error", error:
|
||||
check error.msg == "error"
|
||||
return
|
||||
fail
|
||||
|
||||
test1()
|
||||
test2()
|
||||
|
||||
test "catch can be used to convert exceptions to results":
|
||||
check parseInt("42").catch == 42.success
|
||||
check parseInt("foo").catch.error of ValueError
|
||||
@ -286,6 +349,18 @@ suite "result":
|
||||
let converted = works().option
|
||||
check (converted == @[1, 1, 2, 2, 2].some)
|
||||
|
||||
# Without statement
|
||||
proc someProc(r: ?!int) =
|
||||
without value =? r, error:
|
||||
check error.msg == "some error"
|
||||
return
|
||||
|
||||
check value == 42
|
||||
|
||||
someProc(42.success)
|
||||
someProc(int.failure "some error")
|
||||
|
||||
|
||||
import pkg/questionable/resultsbase
|
||||
|
||||
suite "result compatibility":
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user