From aef59c42eb4de428bcb608cde8fbfd6c292e0797 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 18 Mar 2021 09:50:06 +0100 Subject: [PATCH] Allow optional binding to vars --- questionable/options.nim | 9 +++++++++ questionable/results.nim | 9 +++++++++ testmodules/options/test.nim | 13 +++++++++++++ testmodules/result/test.nim | 13 +++++++++++++ 4 files changed, 44 insertions(+) diff --git a/questionable/options.nim b/questionable/options.nim index eb9c3d5..19a5603 100644 --- a/questionable/options.nim +++ b/questionable/options.nim @@ -1,4 +1,5 @@ import std/options +import std/macros import ./chaining import ./operators @@ -26,6 +27,14 @@ template `=?`*[T](name: untyped{nkIdent}, option: ?T): bool = template name: T {.used.} = option.unsafeGet() option.isSome +macro `=?`*[T](variable: untyped{nkVarTy}, option: ?T): bool = + let name = variable[0] + quote do: + var `name` : typeof(`option`.unsafeGet()) + if `option`.isSome: + `name` = `option`.unsafeGet() + `option`.isSome + template `|?`*[T](option: ?T, fallback: T): T = if option.isSome: option.unsafeGet() diff --git a/questionable/results.nim b/questionable/results.nim index 58255f0..6def9f6 100644 --- a/questionable/results.nim +++ b/questionable/results.nim @@ -1,3 +1,4 @@ +import std/macros import ./resultsbase import ./options import ./operators @@ -41,6 +42,14 @@ template `=?`*[T](name: untyped{nkIdent}, value: ?!T): bool = template name: T {.used.} = value.unsafeGet() value.isOk +macro `=?`*[T](variable: untyped{nkVarTy}, option: ?!T): bool = + let name = variable[0] + quote do: + var `name` : typeof(`option`.unsafeGet()) + if `option`.isOk: + `name` = `option`.unsafeGet() + `option`.isOk + proc option*[T,E](value: Result[T,E]): ?T = if value.isOk: value.unsafeGet.some diff --git a/testmodules/options/test.nim b/testmodules/options/test.nim index 21afd33..8003e6b 100644 --- a/testmodules/options/test.nim +++ b/testmodules/options/test.nim @@ -74,6 +74,19 @@ suite "optionals": if a =? a: check a == 42 + test "=? works with var": + if var a =? 1.some and var b =? 2.some: + check a == 1 + inc a + check a == b + inc b + check b == 3 + else: + fail + + if var a =? int.none: + fail + test "unary operator `-` works for options": check -(-42.some) == 42.some check -(int.none) == int.none diff --git a/testmodules/result/test.nim b/testmodules/result/test.nim index cdbdf5b..0af83ad 100644 --- a/testmodules/result/test.nim +++ b/testmodules/result/test.nim @@ -78,6 +78,19 @@ suite "result": if a =? a: check a == 42 + test "=? works with var": + if var a =? 1.success and var b =? 2.success: + check a == 1 + inc a + check a == b + inc b + check b == 3 + else: + fail + + if var a =? int.failure(error): + fail + test "catch can be used to convert exceptions to results": check parseInt("42").catch == 42.success check parseInt("foo").catch.error of ValueError