# Currying in Python

Kiuhnm kiuhnm03.4t.yahoo.it
Sat Mar 17 02:21:32 CET 2012

```Here we go.

--->
def genCur(f, unique = True, minArgs = -1):
""" Generates a 'curried' version of a function. """
def geng(curArgs, curKwargs):
def g(*args, **kwargs):
nonlocal f, curArgs, curKwargs, minArgs;    # our STATIC data

if len(args) or len(kwargs):
# Allocates data for the next 'g'. We don't want to modify our
# static data.
newArgs = curArgs[:];
newKwargs = dict.copy(curKwargs);

# Adds positional arguments.
newArgs += args;

if unique:
# We don't want repeated keyword arguments.
for k in kwargs.keys():
if k in newKwargs:
raise(Exception("Repeated kw arg while unique = True"));
newKwargs.update(kwargs);

# Checks whether it's time to evaluate f.
if minArgs >= 0 and minArgs <= len(newArgs) + len(newKwargs):
return f(*newArgs, **newKwargs);    # f has enough args
else:
return geng(newArgs, newKwargs);    # f needs some more args
else:
return f(*curArgs, **curKwargs);    # the caller forced the evaluation
return g;
return geng([], {});

def cur(f, minArgs = -1):
return genCur(f, True, minArgs);

def curr(f, minArgs = -1):
return genCur(f, False, minArgs);

# Simple Function.
def f(a, b, c, d, e, f, g = 100):
print(a, b, c, d, e, f, g);

# NOTE: '<====' means "this line prints to the screen".

# Example 1.
c1 = cur(f)(1);
c2 = c1(2, d = 4);              # Note that c is still unbound
c3 = c2(3)(f = 6)(e = 5);       # now c = 3
c3();                           # () forces the evaluation              <====
c4 = c2(30)(f = 60)(e = 50);    # now c = 30
c4();                           # () forces the evaluation              <====

print("\n------\n");

# Example 2.
c1 = curr(f)(1, 2)(3, 4);           # curr = cur with possibly repeated
# keyword args
c2 = c1(e = 5)(f = 6)(e = 10)();    # ops... we repeated 'e' because we <====
# changed our mind about it!
# again, () forces the evaluation

print("\n------\n");

# Example 3.
c1 = cur(f, 6);             # forces the evaluation after 6 arguments
c2 = c1(1, 2, 3);           # num args = 3
c3 = c2(4, f = 6);          # num args = 5
c4 = c3(5);                 # num args = 6 ==> evalution                <====
c5 = c3(5, g = -1);         # num args = 7 ==> evaluation               <====
# we can specify more than 6 arguments, but
# 6 are enough to force the evaluation

print("\n------\n");

# Example 4.
def printTree(func, level = -1):
if level == -1:
printTree(cur(func), level + 1);
elif level == 6:
func(g = '')();     # or just func('')()
else:
printTree(func(0), level + 1);
printTree(func(1), level + 1);

printTree(f);

print("\n------\n");

def f2(*args):
print(", ".join(["%3d"%(x) for x in args]));

def stress(f, n):
if n: stress(f(n), n - 1)
else: f();          # enough is enough

stress(cur(f2), 100);
<---

Kiuhnm

```