aboutsummaryrefslogtreecommitdiff
path: root/std/prelude/results.pk
diff options
context:
space:
mode:
Diffstat (limited to 'std/prelude/results.pk')
-rw-r--r--std/prelude/results.pk136
1 files changed, 136 insertions, 0 deletions
diff --git a/std/prelude/results.pk b/std/prelude/results.pk
new file mode 100644
index 0000000..1209b40
--- /dev/null
+++ b/std/prelude/results.pk
@@ -0,0 +1,136 @@
+## std.results: Result types.
+## This module is imported by default.
+
+use std[options, format]
+
+## The Result type. Represents either success or failure.
+pub type Result[T, E] = union
+ Okay(T)
+ Error(E)
+
+## The Err interface. Useful for dynamically dispatching errors.
+pub type Err = interface
+ str(Self): str
+ dbg(Self): str
+
+## A `Result` type that uses dynamically dispatched errors.
+## The `Error` may be any type implementing `Err`.
+pub type Result[T] = Result[T, ref Err]
+## A `Result` type that only checks for success.
+## Does not contain a value.
+pub type Success[E] = Result[Unit, E]
+
+## Checks if a `Result` type was successful.
+pub func is_ok[T, E](self: Result[T, E]): bool =
+ self of Okay(_)
+## Checks if a `Result` type was not successful.
+pub func is_err[T, E](self: Result[T, E]): bool =
+ self of Error(_)
+
+## Converts from a `Result[T, E]` to an `Option[T]`.
+pub func ok[T, E](self: Result[T, E]): Option[T] =
+ if self of Okay(x):
+ Some(x)
+ else:
+ None()
+## Converts from a `Result[T, E]` to an `Option[E]`.
+pub func err[T, E](self: Result[T, E]): Option[E] =
+ if self of Error(x):
+ Some(x)
+ else:
+ None()
+
+## Applies a function to `T`, if self is `Okay`.
+pub func map[T, E, U](self: Result[T, E], fn: T -> U): Result[U, E] =
+ match self
+ of Okay(x):
+ Okay(fn(x))
+ of Error(e):
+ Error(e)
+## Applies a function to `E`, if self is `Error`.
+pub func map_err[T, E, F](self: Result[T, E], fn: E -> F): Result[T, F] =
+ match self
+ of Error(e):
+ Error(fn(e))
+ of Okay(x):
+ Okay(x)
+
+## Applies a function to `T`, if it exists. Equivalent to `self.map(fn).flatten`.
+pub func flatmap[T, E, U](self: Result[T, E], fn: T -> Result[U, E]): Result[U, E] =
+ match self
+ of Okay(x):
+ fn(x)
+ of Error(e):
+ Error(e)
+## Converts from a `Result[Result[T, E], E]` to a `Result[T, E]`.
+pub func flatten[T, E](self: Result[Result[T, E], E]): Result[T, E] =
+ match self
+ of Okay(Okay(x)):
+ Okay(x)
+ of Okay(Error(e)), Error(e):
+ Error(e)
+
+## Transposes a `Result[Option[T], E]` to an `Option[Result[T, E]]`.
+pub func transpose[T, E](self: Result[Option[T], E]): Option[Result[T, E]] =
+ match self
+ of Okay(Some(x)):
+ Some(Okay(x))
+ of Okay(None()), Error(_):
+ None()
+## Transposes an `Option[Result[T, E]]` to a `Result[Option[T], E]`. Takes a default error.
+pub func transpose[T, E](self: Option[Result[T, E]], error: E): Result[Option[T], E] =
+ match self
+ of Some(Okay(x)):
+ Okay(Some(x))
+ of Some(Error(e)):
+ Error(e)
+ of None():
+ Error(error)
+
+## Returns the inner value or a default.
+pub func get_or[T, E](self: Result[T, E], default: T): T =
+ if self of Okay(x): x
+ else: default
+
+## Directly accesses the inner value. Throws an exception if `Error`.
+pub func ![T, E](self: Result[T, E]): T =
+ match self
+ of Okay(x): x
+ of Error(e): raise e
+## Directly accesses the inner error. Throws an exception of type T if `Okay`.
+pub func get_err[T, E](self: Result[T, E]): E =
+ match self
+ of Error(e): e
+ of Okay(x): raise x
+
+## Indirect access. Propagates `Error`.
+pub macro ?[T, E](self: Result[T, E]) =
+ quote:
+ match `self`
+ of Okay(x): x
+ of Error(e): return Error(e)
+
+## Overloads the `==` operation for use on Results.
+pub func ==[T, E, F](a: Result[T, E], b: Result[T, F]): bool =
+ match (a, b)
+ of (Okay(x), Okay(y)):
+ x == y
+ of _:
+ false
+
+## Overloads the `str()` function for use on Results.
+pub func str[T, E](self: Result[T, E]): str =
+ match self
+ of Some(x):
+ fmt("Okay({})", x.str)
+ of Error(e):
+ fmt("Error({})", e.str)
+
+examples:
+ let x: Error("fuck") = Okay(42)
+ func idk: Result[int, string]
+
+# references:
+# https://doc.rust-lang.org/std/result/enum.Result.html
+# https://github.com/arnetheduck/nim-results
+# https://github.com/codex-storage/questionable