Skip to content

Instantly share code, notes, and snippets.

@Celestial-intelligence
Forked from bedekelly/partials.py
Created March 2, 2020 10:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Celestial-intelligence/2951c41c8b24b8ac245d54d71f138246 to your computer and use it in GitHub Desktop.
Save Celestial-intelligence/2951c41c8b24b8ac245d54d71f138246 to your computer and use it in GitHub Desktop.
Graceful partial functions in Python. https://github.com/bedekelly/minitest for test library used.
import inspect
from minitest import case, tests
from functools import wraps, partial
def makepartial(fn):
"""
This function is a decorator which allows functions with a fixed
number of arguments gracefully to be transformed into partial functions
given too few arguments to execute.
For instance, if `add(1, 2)` returns 3, `add(1)` should return a function
`f` such that `f(2)` returns 3.
"""
@wraps(fn)
def maybepartial(*args, **kwargs):
"""
Either calls and returns the decorated function, or -- if we don't
have enough arguments -- creates a partial function with the given
parameters prefilled.
"""
sig = inspect.signature(fn)
if len(args) + len(kwargs) == len(sig.parameters):
return fn(*args, **kwargs)
return makepartial(partial(fn, *args, **kwargs))
return maybepartial
@makepartial
def add(a, b):
return a + b
# Tests:
@case
def test_correctness(t):
t.check_equal(add(1, 2), 3)
@case
def test_currying(t):
t.check_equal(add(1)(2), add(1, 2))
t.check_equal(add()(1)(2), add(1)(2))
if tests:
tests.run_all()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment