Compare commits

..

No commits in common. "main" and "0.10.13" have entirely different histories.

5 changed files with 11 additions and 49 deletions

View File

@ -12,7 +12,7 @@ Use the [Nimble][3] package manager to add `questionable` to an existing
project. Add the following to its .nimble file: project. Add the following to its .nimble file:
```nim ```nim
requires "questionable >= 0.10.15 & < 0.11.0" requires "questionable >= 0.10.13 & < 0.11.0"
``` ```
If you want to make use of Result types, then you also have to add either the If you want to make use of Result types, then you also have to add either the
@ -151,7 +151,7 @@ have to explicitly import the `questionable/results` module:
import questionable/results import questionable/results
``` ```
You can use `?!` to make a Result type. These Result types either hold a value or You can use `?!` make a Result type. These Result types either hold a value or
an error. For example the type `?!int` is short for `Result[int, ref an error. For example the type `?!int` is short for `Result[int, ref
CatchableError]`. CatchableError]`.
@ -226,7 +226,6 @@ Any Result can be converted to an Option:
```nim ```nim
let converted = works().option # equals @[1, 1, 2, 2, 2].some let converted = works().option # equals @[1, 1, 2, 2, 2].some
let errOption = fails().errorOption # option that is set when the Result holds an error
``` ```
[1]: https://nim-lang.org/docs/options.html [1]: https://nim-lang.org/docs/options.html

View File

@ -1,4 +1,4 @@
version = "0.10.15" version = "0.10.13"
author = "Questionable Authors" author = "Questionable Authors"
description = "Elegant optional types" description = "Elegant optional types"
license = "MIT" license = "MIT"

View File

@ -11,28 +11,26 @@ macro captureBindError*(error: var ref CatchableError, expression): auto =
# name of the error variable as a string literal # name of the error variable as a string literal
let errorVariableName = newLit($error) let errorVariableName = newLit($error)
let evaluated = genSym(nskLet, "evaluated")
quote do: quote do:
# add error variable to the top of the stack # add error variable to the top of the stack
static: errorVariableNames.add(`errorVariableName`) static: errorVariableNames.add(`errorVariableName`)
# evaluate the expression # evaluate the expression
let `evaluated` = `expression` let evaluated = `expression`
# pop error variable from the stack # pop error variable from the stack
static: discard errorVariableNames.pop() static: discard errorVariableNames.pop()
# return the evaluated result # return the evaluated result
`evaluated` evaluated
func unsafeCatchableError[T](_: Option[T]): ref CatchableError = func error[T](_: Option[T]): ref CatchableError =
newException(ValueError, "Option is set to `none`") newException(ValueError, "Option is set to `none`")
func unsafeCatchableError[T](_: ref T): ref CatchableError = func error[T](_: ref T): ref CatchableError =
newException(ValueError, "ref is nil") newException(ValueError, "ref is nil")
func unsafeCatchableError[T](_: ptr T): ref CatchableError = func error[T](_: ptr T): ref CatchableError =
newException(ValueError, "ptr is nil") newException(ValueError, "ptr is nil")
func unsafeCatchableError[Proc: proc | iterator](_: Proc): ref CatchableError = func error[Proc: proc | iterator](_: Proc): ref CatchableError =
newException(ValueError, "proc or iterator is nil") newException(ValueError, "proc or iterator is nil")
macro bindFailed*(expression: typed) = macro bindFailed*(expression: typed) =
@ -51,4 +49,4 @@ macro bindFailed*(expression: typed) =
# check that the error variable is in scope # check that the error variable is in scope
when compiles(`errorVariable`): when compiles(`errorVariable`):
# assign bind error to error variable # assign bind error to error variable
`errorVariable` = `expression`.unsafeCatchableError `errorVariable` = `expression`.error

View File

@ -123,18 +123,6 @@ template toOption*[T, E](value: Result[T, E]): ?T =
value.option value.option
proc unsafeCatchableError*[T, E](value: Result[T, E]): ref CatchableError =
## Returns the error from the Result, converted to `ref CatchableError` if
## necessary. Behaviour is undefined when the result holds a value instead of
## an error.
when E is ref CatchableError:
value.unsafeError
else:
when compiles($value.unsafeError):
newException(ResultFailure, $value.unsafeError)
else:
newException(ResultFailure, "Result is an error")
proc errorOption*[T, E](value: Result[T, E]): ?E = proc errorOption*[T, E](value: Result[T, E]): ?E =
## Returns an Option that contains the error from the Result, if it has one. ## Returns an Option that contains the error from the Result, if it has one.

View File

@ -643,19 +643,6 @@ suite "result":
someProc(42.success) someProc(42.success)
someProc(int.failure "some error") someProc(int.failure "some error")
type TypeWithSideEffect = object
proc `$`*(value: TypeWithSideEffect): string {.sideEffect.} =
discard
suite "result side effects":
test "without statement with error works when `$` has side effects":
proc foo =
without x =? TypeWithSideEffect.failure("error"), error:
discard error
return
fail()
foo()
import pkg/questionable/resultsbase import pkg/questionable/resultsbase
@ -663,7 +650,7 @@ suite "result compatibility":
type R = Result[int, string] type R = Result[int, string]
let good = R.ok 42 let good = R.ok 42
let bad = R.err "some error" let bad = R.err "error"
test "|?, =? and .option work on other types of Result": test "|?, =? and .option work on other types of Result":
check bad |? 43 == 43 check bad |? 43 == 43
@ -681,13 +668,3 @@ suite "result compatibility":
fail fail
without b =? good: without b =? good:
fail fail
test "without statement with error works on other type of Result":
without value =? bad, error:
check error of ResultFailure
check error.msg == "some error"
test "without statement with error works on Result[T, void]":
without value =? Result[int, void].err, error:
check error of ResultFailure
check error.msg == "Result is an error"