Skip to content

Instantly share code, notes, and snippets.

@aib
Last active February 4, 2019 04:57
Show Gist options
  • Save aib/3adc498469d241ce1ec817d5982c7682 to your computer and use it in GitHub Desktop.
Save aib/3adc498469d241ce1ec817d5982c7682 to your computer and use it in GitHub Desktop.
class Piped:
def __init__(self, fn, terminal=False):
self.fn = fn
self.terminal = terminal
self.args = []
self.gotval = False
self.val = None
def __call__(self, *args):
self.args = list(args)
return self
def __or__(self, rhs):
lhs = self._getval()
rhs.args.insert(0, self._getval())
if rhs.terminal:
return rhs._getval()
else:
return rhs
def _getval(self):
# possible race condition
if not self.gotval:
self.gotval = True
self.val = self.fn(*self.args)
return self.val
def piped(fn):
return Piped(fn)
def piped_terminal(fn):
return Piped(fn, terminal=True)
@piped
def return_(x):
return x
@piped
def add(x, y):
return x+y
@piped
def multiply(x, y):
return x*y
@piped_terminal
def print_(x):
print(x)
return_(42) | add(2) | multiply(10) | print_()
# Update: This looks much better
@piped_terminal
def do(x, fn, *args):
fn(*args, x)
return_(42) | add(2) | multiply(10) | do(print)
# Of course, a monadic pipeline is much cleaner:
class MPiped:
def __init__(self, fn):
self.fn = fn
# bind
def __or__(self, rhs):
if rhs is execute:
return self.fn()
return MPiped(lambda:rhs(self.fn()))
# return
def pipe(val):
return MPiped(lambda:val)
# run; we reuse | for readability
def execute():
pass
pipe(42) | (lambda x:x+2) | (lambda x:x*10) | print | execute
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment