## std/results: Result types. ## This module is imported by default. import std/[options, format] pub type Result[T, E] = union Okay: T Error: E # todo: determine the difference between interfaces and types # ErrorInterface? Errorable? Err? pub type Error = interface str(Self): str dbg(Self): str pub type Result[T] = Result[T, ref Error] pub func is_ok[T, E](self: Result[T, E]): bool = self of Okay(_) pub func is_err[T, E](self: Result[T, E]): bool = not self.is_ok ## 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], proc: T -> U): Result[U, E] = match self of Okay(x): Okay(x.proc) 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], proc: E -> F): Result[T, F] = match self of Error(e): Error(e.proc) of Okay(x): Okay(x) ## Applies a function to T, if it exists. Equivalent to .map(func).flatten. pub func flatmap[T, E, U](self: Result[T, E], proc: T -> Result[U, E]): Result[U, E] = match self of Okay(x): x.proc 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(e). pub yeet func `!`[T, E](self: Result[T, E]): T = match self of Okay(x): x of Error(e): raise Exception(e) # todo: syntax?? pub yeet func get_err[T, E](self: Result[T, E]): E = match self of Error(e): e of Okay(x): raise Exception(x) # todo: syntax?? ## Indirect access. Propagates Error. 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