73 lines
1.9 KiB
Python
73 lines
1.9 KiB
Python
from __future__ import annotations
|
|
from typing import TypeVar, Generic, Optional, Callable, Any
|
|
|
|
T = TypeVar('T')
|
|
U = TypeVar('U')
|
|
|
|
|
|
class Maybe(Generic[T]):
|
|
|
|
def __init__(self, value: Optional[T] = None):
|
|
self._value: Optional[T] = value
|
|
|
|
@staticmethod
|
|
def of(obj: T) -> Maybe[T]:
|
|
return Maybe(obj)
|
|
|
|
@staticmethod
|
|
def of_nullable(obj: Optional[T]) -> Maybe[T]:
|
|
return Maybe(obj)
|
|
|
|
@staticmethod
|
|
def empty() -> Maybe[U]:
|
|
return _empty
|
|
|
|
@property
|
|
def value(self) -> T:
|
|
value = self._value
|
|
if not value:
|
|
raise ValueError('Empty Maybe')
|
|
else:
|
|
return value
|
|
|
|
@property
|
|
def is_present(self) -> bool:
|
|
return self._value is not None
|
|
|
|
@property
|
|
def is_empty(self) -> bool:
|
|
return not self.is_present
|
|
|
|
def map(self, transformer: Callable[[T], U]) -> Maybe[U]:
|
|
result: Maybe[U]
|
|
if self.is_present:
|
|
result = Maybe(transformer(self.value))
|
|
else:
|
|
result = Maybe.empty()
|
|
return result
|
|
|
|
def filter(self, predicate: Callable[[T], bool]) -> Maybe[T]:
|
|
return self if self.is_present and predicate(self.value) else Maybe.empty()
|
|
|
|
def flat_map(self, transformer: Callable[[T], Maybe[U]]) -> Maybe[U]:
|
|
return transformer(self.value) if self.is_present else Maybe.empty()
|
|
|
|
def or_else(self, alt: T) -> T:
|
|
return self.value if self.is_present else alt
|
|
|
|
def or_else_throw(self, supplier: Callable[[], Exception]) -> T:
|
|
if self.is_present:
|
|
return self.value
|
|
else:
|
|
raise supplier()
|
|
|
|
def or_else_get(self, supplier: Callable[[], T]) -> Maybe[T]:
|
|
return self if self.is_present else Maybe.of_nullable(supplier())
|
|
|
|
def if_present(self, callback: Callable[[T], U]) -> None:
|
|
if self.is_present:
|
|
callback(self.value)
|
|
|
|
|
|
_empty: Maybe[Any] = Maybe(None)
|