diff --git a/questionable/options.nim b/questionable/options.nim index 9f32ccb..639e98c 100644 --- a/questionable/options.nim +++ b/questionable/options.nim @@ -21,12 +21,24 @@ template `->?`*[T,U](option: ?T, expression: U): ?U = else: 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 = if options[0].isSome and options[1].isSome: expression.some else: 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 = let option = expression template name: T {.used.} = option.unsafeGet() diff --git a/questionable/results.nim b/questionable/results.nim index 545c78a..a2d134b 100644 --- a/questionable/results.nim +++ b/questionable/results.nim @@ -48,6 +48,12 @@ template `->?`*[T,U](value: ?!T, expression: U): ?!U = else: 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 = if values[0].isFailure: V.failure(values[0].error) @@ -56,6 +62,14 @@ template `->?`*[T,U,V](values: (?!T, ?!U), expression: V): ?!V = else: 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 = value.valueOr(fallback) diff --git a/testmodules/options/test.nim b/testmodules/options/test.nim index 92cb725..2047117 100644 --- a/testmodules/options/test.nim +++ b/testmodules/options/test.nim @@ -192,6 +192,23 @@ suite "optionals": 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": var x: ?int diff --git a/testmodules/result/test.nim b/testmodules/result/test.nim index e4fc341..dfeda26 100644 --- a/testmodules/result/test.nim +++ b/testmodules/result/test.nim @@ -175,6 +175,23 @@ suite "result": check fails().isFailure 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": proc works: ?!seq[int] =