results: Add Opt/Result converters (#177)

Add `optError`, `optValue`, to convert back and forth between Opt and Result
These conversions end up being more common than others since "trivial"  success/fail-style API often use Opt while combining such API into combined operations tends to prefer richer error reporting.
This commit is contained in:
Jacek Sieka 2023-05-11 15:34:41 +02:00 committed by GitHub
parent 111d939940
commit 266e9002f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 0 deletions

View File

@ -845,6 +845,20 @@ template unsafeError*[T](self: Result[T, void]) =
## See also: `unsafeGet`
assert not self.oResultPrivate # Emulate field access defect in debug builds
func optValue*[T, E](self: Result[T, E]): Opt[T] =
## Return the value of a Result as an Opt, or none if Result is an error
if self.oResultPrivate:
Opt.some(self.vResultPrivate)
else:
Opt.none(T)
func optError*[T, E](self: Result[T, E]): Opt[E] =
## Return the error of a Result as an Opt, or none if Result is a value
if self.oResultPrivate:
Opt.none(E)
else:
Opt.some(self.eResultPrivate)
# Alternative spellings for get
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()

View File

@ -159,6 +159,12 @@ block:
# Expectations
doAssert rOk.expect("testOk never fails") == 42
# Conversions to Opt
doAssert rOk.optValue() == Opt.some(rOk.get())
doAssert rOk.optError().isNone()
doAssert rErr.optValue().isNone()
doAssert rErr.optError() == Opt.some(rErr.error())
# Question mark operator
func testQn(): Result[int, string] =
let x = ?works() - ?works()
@ -371,6 +377,10 @@ block: # Result[T, void] aka `Opt`
doAssert Opt.some(42).get() == 42
doAssert Opt.none(int).isNone()
# Construct Result from Opt
doAssert oOk.orErr("error").value() == oOk.get()
doAssert oErr.orErr("error").error() == "error"
block: # `cstring` dangling reference protection
type CSRes = Result[void, cstring]