カリー化デコレータ

Python のデコレータはなかなか面白い機能だと思ったので、試しにカリー化を実装してみました。

@curry
def f(x,y,z):
    ...

などと書くと、カリー化されたfが定義されます。まぁ functools.partial があれば全然必要無いシロモノではあるのですが。
複数まとめて関数適用するとき f(x)(y)(z) とか気持ち悪いので、f.apply(x,y,z) みたいに普通っぽく呼び出せるようにもなっています。
可変長引数とは相性悪いです(*付き引数=引数1個ぶんとして扱われます)。

def arity_of(f):
    return len(f.func_code.co_varnames)

class curry:
    def __init__(self, f, n=None, args=None):
        self.func = f
        self.arity = n if n != None else arity_of(f)
        self.args = args   # linked list

    def __call__(self, x):
        f = curry(self.func, self.arity-1, (x, self.args))
        if f.arity <= 0:
            return f.__apply_args()
        else:
            return f

    def __apply_args(self):
        args = []
        l = self.args
        while l != None:
            args.append(l[0])
            l = l[1]
        return self.func(*reversed(args))

    def apply(self, *args):
        f = self
        for x in args:
            f = f(x)
        return f


if __name__=='__main__':
    @curry
    def test(x, y, z):
        print x, y, z
        return x + y * z

    print test(1)(2)(3)
    print test.apply(1,2,3)
    f = test(1)
    g = test.apply(1,2)
    print f.apply(2,3)
    print g(3)