apfel.container.result
A container that holds either a success or a failure.
A Result has two possible states, Ok or Err.
Ok means a successful value is present,
and Err means a failure value is present.
This module also provides a caught decorator, which wraps a partial function to a total function returning a Result.
The Result class, and the ok, err, and caught functions
are exposed in the package namespace.
Rationale
Python raise
is easily missed, since the gradual typing system does not support checked exceptions.
An alternative is to return nullable error flags,
which is cumbersome to work with.
Implementation
Result’s APIs are based on the Rust Result,
and the comparison table is provided below.
Reference Result |
Counterpart |
|---|---|
and |
and_ |
and_then |
and_then |
as_deref |
/ |
as_deref_mut |
/ |
as_mut |
/ |
as_ref |
/ |
cloned |
- |
copied |
/ |
err |
err |
expect |
expect |
expect_err |
expect_err |
flatten |
flatten |
inspect |
~tap |
inspect_err |
~tap_err |
into_err |
- |
into_ok |
- |
is_err |
is_err |
is_err_and |
is_err_and |
is_ok |
is_ok |
is_ok_and |
is_ok_and |
iter |
- |
iter_mut |
/ |
map |
map |
map_err |
map_err |
map_or |
map_or |
map_or_default |
/ |
map_or_else |
map_or_else |
ok |
ok |
or |
or_ |
or_else |
or_else |
transpose |
~transpose |
unwrap |
unwrap |
unwrap_err |
unwrap_err |
unwrap_err_unchecked |
unwrap_err_unchecked |
unwrap_or |
unwrap_or |
unwrap_or_default |
/ |
unwrap_or_else |
unwrap_or_else |
unwrap_unchecked |
unwrap_unchecked |
API#
Resultclass#
class Result(value: T, /, *, is_ok: bool = True)Bases: Monad
A container that holds either a success or a failure. See module-level documentation for more details.
This class is exposed in the package namespace.
__slots__attributeclass attributeinstance attribute#
__slots__ = ('_val', '_is_ok')__and__method#
def __and__(other: Self) -> Self__bool__method#
def __bool__() -> bool__class_getitem__method#
def __class_getitem__(item)__eq__method#
def __eq__(other: Self, /) -> bool__hash__method#
def __hash__() -> int__init__method#
def __init__(value: T, /, *, is_ok: bool = True)__or__method#
def __or__(other: Self) -> Self__repr__method#
def __repr__()__str__method#
def __str__()and_method#
def and_(other: Self, /) -> SelfIf the value is Ok, return a shallow copy of the other Result. Otherwise, return a new Err of type Result[T, E].
and_thenmethod#
def and_then(func: Callable[[T], Result[U, E]], /) -> Result[U, E]If the value is Ok, apply a function that maps the inner value to a Result[U, E] value. Otherwise, return Err of type Result[U, E].
applymethod#
def apply(func: Result[Callable[[T], U], E], /) -> Result[U, E]Implementation of Applicative.apply.
Applies the callable wrapped within a Result to the inner value, if both are Ok.
bindmethod#
def bind(func: Callable[[T], Result[U, E]], /) -> Result[U, E]Implementation of Monad.bind.
Alias of and_then.
donemethod#
def done() -> tuple[T, None] | tuple[None, E]errmethod#
def err() -> Maybe[E]Convert a Result[T, E] to a Maybe[E].
expectmethod#
def expect(message: str, /) -> TUnwrap the inner Ok value, if any. Otherwise, raise a ValueError with a custom message.
expect_errmethod#
def expect_err(message: str, /) -> EUnwrap the inner Err value, if any. Otherwise, raise a ValueError with a custom message.
flattenmethod#
def flatten() -> Result[T_, E]Flatten a nested Result (Result[Result[T, E], E]) value for one level (Result[T, E]).
is_errmethod#
def is_err() -> boolCheck if the value is an Err.
is_err_andmethod#
def is_err_and(pred: Callable[[E], bool], /) -> boolCheck if the value is an Err and satisfies the predicate.
is_okmethod#
def is_ok() -> boolCheck if the value is an Ok.
is_ok_andmethod#
def is_ok_and(pred: Callable[[T], bool], /) -> boolCheck if the value is an Ok and satisfies the predicate.
make_errmethodclassmethod#
def make_err(value: E, /) -> Result[T, E]Construct an Err value.
make_okmethodclassmethod#
def make_ok(value: T, /) -> Result[T, E]Construct an Ok value.
mapmethod#
def map(func: Callable[[T], U], /) -> Result[U, E]Map a Result[T, E] to Result[U, E] by applying a function to a contained Ok value, leaving an Err value untouched.
map_errmethod#
def map_err(func: Callable[[E], F], /) -> Result[T, F]Map a Result[T, E] to Result[T, F] by applying a function to a contained Err value, leaving an Ok value untouched.
map_ormethod#
def map_or(default: U, func: Callable[[T], U]) -> UApply a function to a contained Ok value, or return a provided default value.
map_or_elsemethod#
def map_or_else(default: Callable[[E], U], func: Callable[[T], U]) -> UMap a Result[T, E] to U by applying a function to a contained Ok value, or a fallback function to a contained Err value.
okmethod#
def ok() -> Maybe[T]Convert a Result[T, E] to a Maybe[T].
or_method#
def or_(other: Self, /) -> SelfIf the value is Err, return a shallow copy of the other Result. Otherwise, return a new Ok of type Result[T, F].
or_elsemethod#
def or_else(func: Callable[[E], Self], /) -> SelfReturn a shallow copy of the Result if it contains an Ok value, otherwise call a function to get a result.
puremethodclassmethod#
def pure(value: T, /) -> Result[T, E]Implementation of Applicative.pure, which is equivalent to Result.make_ok.
tapmethod#
def tap(func: Callable[[T], Any], /) -> SelfCall a function with the contained Ok value if it exists.
Unlike Result::inspect,
this method does not require the function to return None.
some_ok = ok(5)some_err = err("error")some_ok.tap(print) # prints: 5some_err.tap(print) # prints nothingtap_errmethod#
def tap_err(func: Callable[[E], Any], /) -> SelfCall a function with the contained Err value if it exists.
throwmethod#
def throw() -> TRaise the contained exception if it is an Err. Otherwise, return the inner Ok value.
transposemethod#
def transpose() -> Maybe[Result[U, E]]Transpose a Result of a Maybe into a Maybe of a Result.
Result[Maybe[T], E] -> Maybe[Result[T, E]]
unwrapmethod#
def unwrap() -> TUnwrap the inner Ok value, if any. Otherwise, raise a ValueError.
unwrap_errmethod#
def unwrap_err() -> EUnwrap the inner Err value, if any. Otherwise, raise a ValueError.
unwrap_err_uncheckedmethod#
def unwrap_err_unchecked() -> EReturn the inner Err value without checking if it is an Err.
unwrap_ormethod#
def unwrap_or(default: T, /) -> TUnwrap the inner Ok value, or return a default value if contains an Err.
unwrap_or_elsemethod#
def unwrap_or_else(func: Callable[[E], T], /) -> TUnwrap the inner Ok value, or return a value computed by a function if contains an Err.
unwrap_uncheckedmethod#
def unwrap_unchecked() -> TReturn the inner value without checking if it is an Ok or Err.
caughtclass#
class caughtA decorator that wraps a partial function to a total function returning a Result.
It supports multiple usages:
- Use as a decorator without arguments (
@caught) to catch all exceptions. - Use as a decorator with specific exception types (either type union
@caught(ExceptionA | ExceptionB)or args@caught(ExceptionA, ExceptionB)) to catch only those exceptions. - Use as a higher-order function by passing the target function (
caught(func)) to catch all exceptions. - Use as a higher-order function with specific exception types as args (
caught(func, ExceptionA, ExceptionB)) to catch only those exceptions. - Use generic syntax to provide type hints (
@caught[ExceptionA],@caught[ExceptionA](),caught[ExceptionA]()), without affecting runtime behavior.
This function is exposed in the package namespace.
@caught(ZeroDivisionError)def divide(a: float, b: float) -> float: return a / b
divide(4, 2) # Ok(2.0)divide(4, 0) # Err(ZeroDivisionError)__class_getitem__method#
def __class_getitem__(item: type[F]) -> type[caught[F, T]]__new__method#
def __new__(first=None, /, *exceptions: type[Es]) -> Callable[[Callable[P, U]], Callable[P, Result[U, E]]] | Callable[[Callable[P, U]], Callable[P, Result[U, F]]] | Callable[[Callable[P, U]], Callable[P, Result[U, E0 | Es]]] | Callable[P, Result[U, Es]] | Callable[P, Result[U, E]]errclass#
class errConstruct an Err value.
This function is exposed in the package namespace.
some_err = err("Something went wrong")match some_err: case ok(value): print(f"Got an Ok with value: {value}") case err(error): print(f"Got an Err with error: {error}")
# Output: Got an Err with error: Something went wrong__match_args__attributeclass attributeinstance attribute#
__match_args__ = ('_val')__slots__attributeclass attributeinstance attribute#
__slots__ = ()okclass#
class okConstruct an Ok value.
This function is exposed in the package namespace.
some_ok = ok(42)
match some_ok: case ok(value): print(f"Got an Ok with value: {value}") case err(error): print(f"Got an Err with error: {error}")
# Output: Got an Ok with value: 42__match_args__attributeclass attributeinstance attribute#
__match_args__ = ('_val')__slots__attributeclass attributeinstance attribute#
__slots__ = ()