diff --git a/Readme.md b/Readme.md index ac4ab4c..a3833b8 100644 --- a/Readme.md +++ b/Readme.md @@ -126,6 +126,19 @@ let z = x |? 3 # z equals 3 ``` +### Obtaining value with ! + +The `!` operator returns the value of an Option when you're absolutely sure that +it contains a value. + +```nim +x = 42.some +let dare = !x # dare equals 42 + +x = int.none +let crash = !x # raises a Defect +``` + ### Operators The operators `[]`, `-`, `+`, `@`, `*`, `/`, `div`, `mod`, `shl`, `shr`, `&`, diff --git a/questionable/options.nim b/questionable/options.nim index 639e98c..b576627 100644 --- a/questionable/options.nim +++ b/questionable/options.nim @@ -7,7 +7,7 @@ import ./without include ./errorban -export options +export options except get export chaining export indexing export without @@ -15,6 +15,9 @@ export without template `?`*(T: typed): type Option[T] = Option[T] +template `!`*[T](option: ?T): T = + option.get + template `->?`*[T,U](option: ?T, expression: U): ?U = if option.isSome: expression.some diff --git a/questionable/results.nim b/questionable/results.nim index a2d134b..47ad46f 100644 --- a/questionable/results.nim +++ b/questionable/results.nim @@ -8,7 +8,7 @@ import ./without include ./errorban -export resultsbase except ok, err, isOk, isErr +export resultsbase except ok, err, isOk, isErr, get export chaining export indexing export without @@ -18,6 +18,9 @@ type ResultFailure* = object of CatchableError template `?!`*(T: typed): type Result[T, ref CatchableError] = Result[T, ref CatchableError] +template `!`*[T](value: ?!T): T = + value.get + proc success*[T](value: T): ?!T = ok(?!T, value) diff --git a/testmodules/options/test.nim b/testmodules/options/test.nim index 2047117..d6b0087 100644 --- a/testmodules/options/test.nim +++ b/testmodules/options/test.nim @@ -11,6 +11,10 @@ suite "optionals": check (?string is Option[string]) check (?seq[bool] is Option[seq[bool]]) + test "! gets value or raises Defect": + check !42.some == 42 + expect Defect: discard !int.none + test ".? can be used for chaining optionals": let a: ?seq[int] = @[41, 42].some let b: ?seq[int] = seq[int].none @@ -25,10 +29,10 @@ suite "optionals": test ".? chain can be followed by . calls and operators": let a = @[41, 42].some - check a.?len.get == 2 - check a.?len.get.uint8.uint64 == 2'u64 - check a.?len.get() == 2 - check a.?len.get().uint8.uint64 == 2'u64 + check a.?len.unsafeGet == 2 + check a.?len.unsafeGet.uint8.uint64 == 2'u64 + check a.?len.unsafeGet() == 2 + check a.?len.unsafeGet().uint8.uint64 == 2'u64 check a.?deduplicate()[0].?uint8.?uint64 == 41'u64.some check a.?len + 1 == 3.some check a.?deduplicate()[0] + 1 == 42.some @@ -147,10 +151,10 @@ suite "optionals": check table.?["a"].isSome check table.?["a"].isSome() check table.?["a"][0] == 41.some - check table.?["a"].?len.get == 2 - check table.?["a"].?len.get.uint8.uint64 == 2'u64 - check table.?["a"].?len.get() == 2 - check table.?["a"].?len.get().uint8.uint64 == 2'u64 + check table.?["a"].?len.unsafeGet == 2 + check table.?["a"].?len.unsafeGet.uint8.uint64 == 2'u64 + check table.?["a"].?len.unsafeGet() == 2 + check table.?["a"].?len.unsafeGet().uint8.uint64 == 2'u64 check table.?["a"].?deduplicate()[0].?uint8.?uint64 == 41'u64.some check table.?["a"].?len + 1 == 3.some check table.?["a"].?deduplicate()[0] + 1 == 42.some @@ -277,6 +281,16 @@ suite "optionals": let z = x |? 3 check z == 3 + # Obtaining value with ! + + x = 42.some + let dare = !x + check dare == 42 + + x = int.none + expect Defect: + let crash {.used.} = !x + # Operators numbers = @[1, 2, 3].some diff --git a/testmodules/result/test.nim b/testmodules/result/test.nim index dfeda26..24cd39f 100644 --- a/testmodules/result/test.nim +++ b/testmodules/result/test.nim @@ -14,6 +14,10 @@ suite "result": check (?!string is Result[string, ref CatchableError]) check (?!seq[bool] is Result[seq[bool], ref CatchableError]) + test "! gets value or raises Defect": + check !42.success == 42 + expect Defect: discard !int.failure error + test ".? can be used for chaining results": let a: ?!seq[int] = @[41, 42].success let b: ?!seq[int] = seq[int].failure error @@ -28,10 +32,10 @@ suite "result": test ".? chain can be followed by . calls and operators": let a = @[41, 42].success - check (a.?len.get == 2) - check (a.?len.get.uint8.uint64 == 2'u64) - check (a.?len.get() == 2) - check (a.?len.get().uint8.uint64 == 2'u64) + check (a.?len.unsafeGet == 2) + check (a.?len.unsafeGet.uint8.uint64 == 2'u64) + check (a.?len.unsafeGet() == 2) + check (a.?len.unsafeGet().uint8.uint64 == 2'u64) check (a.?deduplicate()[0].?uint8.?uint64 == 41'u64.success) check (a.?len + 1 == 3.success) check (a.?deduplicate()[0] + 1 == 42.success)