Last active
June 28, 2017 07:32
-
-
Save mx-moth/8cf1b6ce0d6d9b201913a4f0519b976e to your computer and use it in GitHub Desktop.
Automatic partially-applied binary operators ala Haskell, for Python
This file contains hidden or 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
class Comparator(): | |
"""Support 'partial binding' of built in operators.""" | |
def __call__(self, a): | |
"""For support of nested PendingOperations, comparator(a) == a""" | |
return a | |
# A bunch of boring operators | |
def __lt__(self, b): | |
return PendingOperation(lambda a: self(a) < b) | |
def __gt__(self, b): | |
return PendingOperation(lambda a: self(a) > b) | |
def __eq__(self, b): | |
return PendingOperation(lambda a: self(a) == b) | |
def __mod__(self, b): | |
return PendingOperation(lambda a: self(a) % b) | |
def __and__(self, b): | |
return PendingOperation(lambda a: self(a) & b) | |
def __or__(self, b): | |
return PendingOperation(lambda a: self(a) | b) | |
def __add__(self, b): | |
return PendingOperation(lambda a: self(a) + b) | |
def __sub__(self, b): | |
return PendingOperation(lambda a: self(a) - b) | |
def __mult__(self, b): | |
return PendingOperation(lambda a: self(a) * b) | |
def __truediv__(self, b): | |
return PendingOperation(lambda a: self(a) / b) | |
def __floordiv__(self, b): | |
return PendingOperation(lambda a: self(a) // b) | |
def __getitem__(self, key): | |
return PendingOperation(lambda a: self(a)[key]) | |
def __getattr__(self, attr): | |
return PendingOperation(lambda a: getattr(self(a), attr)) | |
class PendingOperation(Comparator): | |
"""Support for chainable partially bound functions""" | |
def __init__(self, fn): | |
self.fn = fn | |
def __call__(self, value): | |
value = self.fn(value) | |
return value | |
# Various aliases for a comparator instance. Pick one you like | |
_ = x = thing = item = Comparator() | |
def test(): | |
"""Put the comparator through its paces""" | |
assert (thing < 10)(5) | |
assert (thing > 10)(15) | |
assert list(filter(_ < 5, range(10))) == [0, 1, 2, 3, 4] | |
assert list(filter(x % 2 == 0, range(10))) == [0, 2, 4, 6, 8] | |
assert (x['hello'])({'hello': 'world'}) == 'world' | |
print("All good!") | |
if __name__ == '__main__': | |
test() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment