Skip to content

Instantly share code, notes, and snippets.

@zhangyoufu
Created May 1, 2013 14:21
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 zhangyoufu/5495522 to your computer and use it in GitHub Desktop.
Save zhangyoufu/5495522 to your computer and use it in GitHub Desktop.
__all__ = ['curry']
# Modified from http://mtomassoli.wordpress.com/2012/03/18/currying-in-python/
# Not perfect, but almost there
# Note: func_name must be ascii string
def generate_curry_func_name(func, *args, **kwargs):
argument = map(repr, args)
argument += [u'%s=%s' % (k,repr(kwargs[k])) for k in func.func_code.co_varnames if k in kwargs]
argument = u', '.join(argument)
return func.func_name + ('(%s)' % argument.encode('raw_unicode_escape') if argument else '')
def curry(func, unique_kwargs=True, require_force_evaluate=False):
""" Generates a 'curried' version of a function.
Example:
>>> @curry
>>> def f(a,b,c,d=1,e=2,f=3):
... print 'Hello', a, b, c, d, e, f
...
>>> f(1,f=1)(c=3, d=3)(2)
Hello 1 2 3 3 2 1
"""
num_default_args = len(func.func_defaults)
required_args = set(func.func_code.co_varnames[:-num_default_args])
def g(*args, **kwargs):
def f(*_args, **_kwargs):
if _args or _kwargs:
new_args = args + _args
new_kwargs = dict.copy(kwargs)
if unique_kwargs and not set(_kwargs.keys()).isdisjoint(new_kwargs):
raise ValueError('Duplicate keyword argument while currying')
new_kwargs.update(_kwargs)
# check whether it's time to evaluate
if not require_force_evaluate and \
len(required_args.intersection(new_kwargs.keys())) + \
len(new_args) >= len(required_args):
return func(*new_args, **new_kwargs)
else:
return g(*new_args, **new_kwargs)
else:
# force evaluation
return func(*args, **kwargs)
f.func_name = generate_curry_func_name(func, *args, **kwargs)
return f
return g()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment