Skip to content

Instantly share code, notes, and snippets.

@nvbn
Created August 9, 2016 11:44
Show Gist options
  • Save nvbn/d71fee5b1cad58d5eb80e369194f4155 to your computer and use it in GitHub Desktop.
Save nvbn/d71fee5b1cad58d5eb80e369194f4155 to your computer and use it in GitHub Desktop.
Partial application and piping without magic
from functools import wraps
class Partial:
def __init__(self, fn, args, kwargs):
self._fn = fn
self._args = args
self._kwargs = kwargs
def __call__(self, replacement):
args = [replacement if arg is ... else arg
for arg in self._args]
kwargs = {key: replacement if val is ... else val
for key, val in self._kwargs.items()}
return self._fn(*args, **kwargs)
def __rmatmul__(self, replacement):
return self(replacement)
def __repr__(self):
return '<Partial: {}(*{}, **{})>'.format(
self._fn.__name__, repr(self._args), repr(self._kwargs))
def ellipsis_partial(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
ellipsises = (list(args) + list(kwargs.values())).count(...)
if ellipsises > 1:
raise TypeError('Only one ... allowed as an argument.')
elif ellipsises:
return Partial(fn, args, kwargs)
else:
return fn(*args, **kwargs)
return wrapper
def _(fn, *args, **kwargs):
return ellipsis_partial(fn)(*args, **kwargs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment