Skip to content

Instantly share code, notes, and snippets.

@purefunctor
Last active June 18, 2020 03:00
Show Gist options
  • Save purefunctor/29c279ef6bb0a6c775b4dfdd8280d703 to your computer and use it in GitHub Desktop.
Save purefunctor/29c279ef6bb0a6c775b4dfdd8280d703 to your computer and use it in GitHub Desktop.
# switch_0.py
# Runs actions/values as they are found
class FirstMatchFound(Exception):
pass
class InvalidResultTypeError(Exception):
pass
class UnexhaustivePatternsError(Exception):
pass
class Action:
def __init__(self, func, *args, **kwargs):
self.func = func
self.args = args
self.kwargs = kwargs
def __call__(self):
return self.func(*self.args, **self.kwargs)
class Value:
def __init__(self, value):
self.value = value
def __call__(self):
return self.value
class Switch:
def __init__(self, expected, *, default=None):
self.against = None
self.default = default
self.expected = expected
self.result = None
def __call__(self, against):
self.against = against
return self
def __rshift__(self, value_or_action):
if not isinstance(value_or_action, (Action, Value)):
raise InvalidResultTypeError("Expecting either 'Action' or 'Value'")
if self.expected == self.against:
self.result = value_or_action()
raise FirstMatchFound(f"Match found {self.result}")
def __enter__(self):
return self
def __exit__(self, exception, value, traceback):
if exception is FirstMatchFound:
return True
elif exception is InvalidResultTypeError:
return True
elif self.default is None:
raise UnexhaustivePatternsError
self.result = self.default()
return False
with Switch("foo") as Case:
Case("foo") >> Action(print, "Hello, World")
Case("bar") >> Value("Hello, Bar")
# switch_1.py
# Runs actions/values on exit
class FirstMatchFound(Exception):
pass
class InvalidResultTypeError(Exception):
pass
class UnexhaustivePatternsError(Exception):
pass
class Action:
def __init__(self, func, *args, **kwargs):
self.func = func
self.args = args
self.kwargs = kwargs
def __call__(self):
return self.func(*self.args, **self.kwargs)
class Value:
def __init__(self, value):
self.value = value
def __call__(self):
return self.value
class Switch:
def __init__(self, expected, *, default=None):
self.expected = expected
self.default = default
self.mapping = {}
self.current = None
self.result = None
def __call__(self, current):
self.current = current
return self
def __rshift__(self, value_or_action):
if not isinstance(value_or_action, (Action, Value)):
raise InvalidResultTypeError("Expecting either 'Action' or 'Value'")
self.mapping[self.current] = value_or_action
def __enter__(self):
return self
def __exit__(self, exception, value, traceback):
if exception is InvalidResultTypeError:
return True
if self.expected in self.mapping:
self.result = self.mapping[self.expected]()
return False
elif self.default is None:
raise UnexhaustivePatternsError
else:
self.result = self.default()
return False
with Switch("foo") as Case:
Case("foo") >> Action(print, "Foo")
Case("bar") >> Action(print, "Bar")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment