Python でカリー化

関数をカリー化するデコレータを書いてみました。

def curried(func):
    arg_count = func.__code__.co_argcount
    l = ['lambda arg_{0}: '.format(n) for n in range(arg_count)]
    l.append('func(')
    l.extend(['arg_{0}, '.format(n) for n in range(arg_count - 1)])
    l.extend(['arg_', str(arg_count - 1), ')'])
    return eval(''.join(l), {'func': func})


def rcurried(func):
    arg_count = func.__code__.co_argcount
    l = ['lambda arg_{0}: '.format(n) for n in range(arg_count - 1, -1, -1)]
    l.append('func(')
    l.extend(['arg_{0}, '.format(n) for n in range(arg_count - 1)])
    l.extend(['arg_', str(arg_count - 1), ')'])
    return eval(''.join(l), {'func': func})

curriedは引数リストの左からカリー化します。

rcurriedは引数リストの右からカリー化します。

こんな感じで使えます。

@curried
def create_message(s, v, o):
    return  s + ' ' + v + ' ' + o + '.'

create_message('I')('love')('you')
#=> 'I love you.'

@rcurried
def create_message(s, v, o):
    return  s + ' ' + v + ' ' + o + '.'

create_message('me')("don't love")('You')
#=> "You don't love me."