Created
February 24, 2021 08:30
-
-
Save fre-sch/16dfe16fda1a2a1d2ee7083634d65271 to your computer and use it in GitHub Desktop.
Chainable None-Aware Wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from dataclasses import dataclass | |
class Maybe: | |
def __init__(self, value): | |
self.value = value | |
def bind(self, f): | |
if self.value is None: | |
return self | |
result = f(self.value) | |
if isinstance(result, Maybe): | |
return result | |
return Maybe(result) | |
def __iter__(self): | |
if self.value is None: | |
return | |
yield self.value | |
def __bool__(self): | |
return self.value is not None | |
def __getattr__(self, item): | |
return self.bind(lambda v: getattr(v, item)) | |
# def __setattr__(self, key, value): | |
# return self.bind(lambda v: setattr(v, key, value)) | |
def __getitem__(self, item): | |
return self.bind(lambda v: v[item]) | |
# def __setitem__(self, key, value): | |
# def setter(v): v[key] = value | |
# return self.bind(setter) | |
def __invert__(self): | |
return next(iter(self), None) | |
def __call__(self, *a, **kw): | |
return self.bind(lambda v: v(*a, **kw)) | |
@dataclass | |
class Cart: | |
order: object | |
class Order: | |
def __init__(self, items, currency): | |
self.items = items | |
self.currency = currency | |
def total(self): | |
return sum( | |
~Maybe(order_item).price or 0 | |
for order_item in self.items | |
) | |
@dataclass | |
class OrderItem: | |
price: int | |
cart = Cart( | |
Order( | |
[ | |
OrderItem(100), | |
OrderItem(100), | |
None | |
], | |
"EUR" | |
) | |
) | |
assert ~Maybe(cart).order.total() == 200 | |
print(~Maybe(cart).order.items[2].price) | |
cart.order = None | |
assert ~Maybe(cart).order.total() is None |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment