Avoid wrapping option in option and result in result

This commit is contained in:
Mark Spanbroek 2021-04-17 19:50:02 +02:00
parent d82581244c
commit fa56587bcd
4 changed files with 60 additions and 0 deletions

View File

@ -21,12 +21,24 @@ template `->?`*[T,U](option: ?T, expression: U): ?U =
else: else:
U.none U.none
template `->?`*[T,U](option: ?T, expression: ?U): ?U =
if option.isSome:
expression
else:
U.none
template `->?`*[T,U,V](options: (?T, ?U), expression: V): ?V = template `->?`*[T,U,V](options: (?T, ?U), expression: V): ?V =
if options[0].isSome and options[1].isSome: if options[0].isSome and options[1].isSome:
expression.some expression.some
else: else:
V.none V.none
template `->?`*[T,U,V](options: (?T, ?U), expression: ?V): ?V =
if options[0].isSome and options[1].isSome:
expression
else:
V.none
template `=?`*[T](name: untyped{nkIdent}, expression: ?T): bool = template `=?`*[T](name: untyped{nkIdent}, expression: ?T): bool =
let option = expression let option = expression
template name: T {.used.} = option.unsafeGet() template name: T {.used.} = option.unsafeGet()

View File

@ -48,6 +48,12 @@ template `->?`*[T,U](value: ?!T, expression: U): ?!U =
else: else:
expression.success expression.success
template `->?`*[T,U](value: ?!T, expression: ?!U): ?!U =
if value.isFailure:
U.failure(value.error)
else:
expression
template `->?`*[T,U,V](values: (?!T, ?!U), expression: V): ?!V = template `->?`*[T,U,V](values: (?!T, ?!U), expression: V): ?!V =
if values[0].isFailure: if values[0].isFailure:
V.failure(values[0].error) V.failure(values[0].error)
@ -56,6 +62,14 @@ template `->?`*[T,U,V](values: (?!T, ?!U), expression: V): ?!V =
else: else:
expression.success expression.success
template `->?`*[T,U,V](values: (?!T, ?!U), expression: ?!V): ?!V =
if values[0].isFailure:
V.failure(values[0].error)
elif values[1].isFailure:
V.failure(values[1].error)
else:
expression
template `|?`*[T,E](value: Result[T,E], fallback: T): T = template `|?`*[T,E](value: Result[T,E], fallback: T): T =
value.valueOr(fallback) value.valueOr(fallback)

View File

@ -192,6 +192,23 @@ suite "optionals":
check 40.some >= 42 == false.some check 40.some >= 42 == false.some
check 40.some > 42 == false.some check 40.some > 42 == false.some
test ".? avoids wrapping option in option":
let a = 41.some
proc b(x: int): ?int =
some x + 1
check a.?b == 42.some
test "lifted operators avoid wrapping option in option":
let a = 40.some
let b = 2.some
func `&`(x, y: int): ?int =
some x + y
check (a & b) == 42.some
test "examples from readme work": test "examples from readme work":
var x: ?int var x: ?int

View File

@ -175,6 +175,23 @@ suite "result":
check fails().isFailure check fails().isFailure
check fails().error.msg == "some error" check fails().error.msg == "some error"
test ".? avoids wrapping result in result":
let a = 41.success
proc b(x: int): ?!int =
success x + 1
check a.?b == 42.success
test "lifted operators avoid wrapping result in result":
let a = 40.success
let b = 2.success
func `&`(x, y: int): ?!int =
success x + y
check (a & b) == 42.success
test "examples from readme work": test "examples from readme work":
proc works: ?!seq[int] = proc works: ?!seq[int] =