Curry in Python

I'm... not sure how I got here, but this is what I spent my evening doing. I have been using partial in python on occasion, but it's kind of annoying to have to be so explicit with it any time you want to use partial application.

def curry(fn):
    arity = fn.__code__.co_argcount
    def f(*fargs):
        if len(fargs) > arity:
            raise RuntimeError(
                'Received {} arguments, but {} takes {} arguments'.format(
                    len(fargs), fn, arity))
        def g(*gargs):
            argcount = len(fargs) + len(gargs)
            return (partial(f, *(fargs + gargs))
                    if argcount < arity
                    else f(*(fargs + gargs)))
        return g if len(fargs) < arity else fn(*fargs)
    return f

So I goofed around a bit until I came up with this. And, it works!

In case you don't know what currying is, it makes this possible:

def add_three(a, b, c):
  return a + b + c

add_three(1, 2, 3)  # 6
curry(add_three)(1, 2, 3)  # 6
curry(add_three)(1, 2)(3)  # 6
curry(add_three)(1)(2, 3)  # 6
curry(add_three)(1)(2)(3)  # 6
Show Comments