Lift operators so that they can be used on options and results
This commit is contained in:
parent
dfe4e3cc4b
commit
1b47843012
|
@ -31,3 +31,44 @@ template `=?`*[T](name: untyped{nkIdent}, option: ?T): bool =
|
|||
template name: T {.used.} = option.unsafeGet()
|
||||
option.isSome
|
||||
|
||||
template liftPrefix(_: type Option, operator: untyped) =
|
||||
|
||||
template `operator`*(a: ?typed): ?typed =
|
||||
type T = type(`operator`(a.unsafeGet))
|
||||
if x =? a:
|
||||
`operator`(x).some
|
||||
else:
|
||||
T.none
|
||||
|
||||
template liftInfix(_: type Option, operator: untyped) =
|
||||
|
||||
template `operator`*(a: ?typed, b: ?typed): ?typed =
|
||||
type T = type(`operator`(a.unsafeGet, b.unsafeGet))
|
||||
if x =? a and y =? b:
|
||||
`operator`(x, y).some
|
||||
else:
|
||||
T.none
|
||||
|
||||
template `operator`*(a: ?typed, b: typed): ?typed =
|
||||
type T = type(`operator`(a.unsafeGet, b))
|
||||
if x =? a:
|
||||
`operator`(x, b).some
|
||||
else:
|
||||
T.none
|
||||
|
||||
Option.liftPrefix(`-`)
|
||||
Option.liftPrefix(`+`)
|
||||
Option.liftPrefix(`@`)
|
||||
Option.liftInfix(`*`)
|
||||
Option.liftInfix(`/`)
|
||||
Option.liftInfix(`div`)
|
||||
Option.liftInfix(`mod`)
|
||||
Option.liftInfix(`shl`)
|
||||
Option.liftInfix(`shr`)
|
||||
Option.liftInfix(`+`)
|
||||
Option.liftInfix(`-`)
|
||||
Option.liftInfix(`&`)
|
||||
Option.liftInfix(`<=`)
|
||||
Option.liftInfix(`<`)
|
||||
Option.liftInfix(`>=`)
|
||||
Option.liftInfix(`>`)
|
||||
|
|
|
@ -33,3 +33,47 @@ template `|?`*[T](value: ?!T, fallback: T): T =
|
|||
template `=?`*[T](name: untyped{nkIdent}, value: ?!T): bool =
|
||||
template name: T {.used.} = value.unsafeGet()
|
||||
value.isOk
|
||||
|
||||
template liftPrefix(_: type Result, operator: untyped) =
|
||||
|
||||
template `operator`*(a: ?!typed): ?!typed =
|
||||
type T = type(`operator`(a.unsafeGet))
|
||||
if x =? a:
|
||||
`operator`(x).success
|
||||
else:
|
||||
T.failure(a.error)
|
||||
|
||||
template liftInfix(_: type Result, operator: untyped) =
|
||||
|
||||
template `operator`*(a: ?!typed, b: ?!typed): ?!typed =
|
||||
type T = type(`operator`(a.unsafeGet, b.unsafeGet))
|
||||
if x =? a and y =? b:
|
||||
`operator`(x, y).success
|
||||
elif a.isErr:
|
||||
T.failure(a.error)
|
||||
else:
|
||||
T.failure(b.error)
|
||||
|
||||
template `operator`*(a: ?!typed, b: typed): ?!typed =
|
||||
type T = type(`operator`(a.unsafeGet, b))
|
||||
if x =? a:
|
||||
`operator`(x, b).success
|
||||
else:
|
||||
T.failure(a.error)
|
||||
|
||||
Result.liftPrefix(`-`)
|
||||
Result.liftPrefix(`+`)
|
||||
Result.liftPrefix(`@`)
|
||||
Result.liftInfix(`*`)
|
||||
Result.liftInfix(`/`)
|
||||
Result.liftInfix(`div`)
|
||||
Result.liftInfix(`mod`)
|
||||
Result.liftInfix(`shl`)
|
||||
Result.liftInfix(`shr`)
|
||||
Result.liftInfix(`+`)
|
||||
Result.liftInfix(`-`)
|
||||
Result.liftInfix(`&`)
|
||||
Result.liftInfix(`<=`)
|
||||
Result.liftInfix(`<`)
|
||||
Result.liftInfix(`>=`)
|
||||
Result.liftInfix(`>`)
|
||||
|
|
|
@ -56,3 +56,32 @@ suite "optionals":
|
|||
let a = 42.some
|
||||
if a =? a:
|
||||
check a == 42
|
||||
|
||||
test "unary operator `-` works for options":
|
||||
check -(-42.some) == 42.some
|
||||
check -(int.none) == int.none
|
||||
|
||||
test "other unary operators work for options":
|
||||
check +(42.some) == 42.some
|
||||
check @([1, 2].some) == (@[1, 2]).some
|
||||
|
||||
test "binary operator `+` works for options":
|
||||
check 40.some + 2.some == 42.some
|
||||
check 40.some + 2 == 42.some
|
||||
check int.none + 2 == int.none
|
||||
check 40.some + int.none == int.none
|
||||
check int.none + int.none == int.none
|
||||
|
||||
test "other binary operators work for options":
|
||||
check 21.some * 2 == 42.some
|
||||
check 84'f.some / 2'f == 42'f.some
|
||||
check 84.some div 2 == 42.some
|
||||
check 85.some mod 43 == 42.some
|
||||
check 0b00110011.some shl 1 == 0b01100110.some
|
||||
check 0b00110011.some shr 1 == 0b00011001.some
|
||||
check 44.some - 2 == 42.some
|
||||
check "f".some & "oo" == "foo".some
|
||||
check 40.some <= 42 == true.some
|
||||
check 40.some < 42 == true.some
|
||||
check 40.some >= 42 == false.some
|
||||
check 40.some > 42 == false.some
|
||||
|
|
|
@ -63,3 +63,32 @@ suite "result":
|
|||
test "catch can be used to convert exceptions to results":
|
||||
check parseInt("42").catch == 42.success
|
||||
check parseInt("foo").catch.error of ValueError
|
||||
|
||||
test "unary operator `-` works for results":
|
||||
check -(-42.success) == 42.success
|
||||
check -(int.failure(error)) == int.failure(error)
|
||||
|
||||
test "other unary operators work for results":
|
||||
check +(42.success) == 42.success
|
||||
check @([1, 2].success) == (@[1, 2]).success
|
||||
|
||||
test "binary operator `+` works for results":
|
||||
check 40.success + 2.success == 42.success
|
||||
check 40.success + 2 == 42.success
|
||||
check int.failure(error) + 2 == int.failure(error)
|
||||
check 40.success + int.failure(error) == int.failure(error)
|
||||
check int.failure(error) + int.failure(error) == int.failure(error)
|
||||
|
||||
test "other binary operators work for results":
|
||||
check (21.success * 2 == 42.success)
|
||||
check (84'f.success / 2'f == 42'f.success)
|
||||
check (84.success div 2 == 42.success)
|
||||
check (85.success mod 43 == 42.success)
|
||||
check (0b00110011.success shl 1 == 0b01100110.success)
|
||||
check (0b00110011.success shr 1 == 0b00011001.success)
|
||||
check (44.success - 2 == 42.success)
|
||||
check ("f".success & "oo" == "foo".success)
|
||||
check (40.success <= 42 == true.success)
|
||||
check (40.success < 42 == true.success)
|
||||
check (40.success >= 42 == false.success)
|
||||
check (40.success > 42 == false.success)
|
||||
|
|
Loading…
Reference in New Issue