diff --git a/toolz/functoolz.py b/toolz/functoolz.py index 7709f15b..7ff35010 100644 --- a/toolz/functoolz.py +++ b/toolz/functoolz.py @@ -821,6 +821,36 @@ def __name__(self): except AttributeError: return 'excepting' +@curry +def uncurry(func, arg): + """ Call the function unpacking the argument tuple / dict provided. + + This function is curried. + + >>> def f(a, b, c): + ... return a + b + c + ... + >>> f(1, 2, 3) + 6 + >>> f(1, 2, 3) == uncurry(f, (1, 2, 3)) + True + >>> def g(foo, bar): + ... return foo + bar + ... + >>> g(1, 2) + 3 + >>> g(1, 2) == uncurry(g, {'foo': 1, 'bar': 2}) + True + """ + if ( + hasattr(arg, 'keys') + and callable(arg.keys) + and hasattr(arg, '__getitem__') + and callable(arg.__getitem__) + ): + return func(**arg) + else: + return func(*arg) def _check_sigspec(sigspec, func, builtin_func, *builtin_args): if sigspec is None: diff --git a/toolz/tests/test_functoolz.py b/toolz/tests/test_functoolz.py index a28c2a77..b37638f1 100644 --- a/toolz/tests/test_functoolz.py +++ b/toolz/tests/test_functoolz.py @@ -1,8 +1,8 @@ import inspect import toolz from toolz.functoolz import (thread_first, thread_last, memoize, curry, - compose, compose_left, pipe, complement, do, juxt, - flip, excepts, apply) + compose, compose_left, pipe, complement, do, juxt, + flip, excepts, apply, uncurry) from operator import add, mul, itemgetter from toolz.utils import raises from functools import partial @@ -797,3 +797,20 @@ def raise_(a): excepting = excepts(object(), object(), object()) assert excepting.__name__ == 'excepting' assert excepting.__doc__ == excepts.__doc__ + + +def test_uncurry(): + assert uncurry(lambda x, y: 2 * x + y)((2, 1)) == 5 + assert uncurry(lambda foo, bar: 2 * foo + bar)({'foo': 2, 'bar': 1}) == 5 + + def test_args(*args): + if len(args) == 0: + return 0 + else: + return args[-1] + 2 * test_args(*args[:-1]) + assert uncurry(test_args)((3, 2, 1)) == 17 + + def test_kwargs(**kwargs): + return ", ".join(f"{k}={v}" for k, v in kwargs.items()) + + assert uncurry(test_kwargs)({"a": 1, "b": 2, "c": 3}) == "a=1, b=2, c=3" \ No newline at end of file