Salim Fadhley
Salim Fadhley

Reputation: 23008

Apply a series of functions to some arguments

I'm after something a little more elegant than this.

What is the most elegant way to implement F such that:

F(a,b,c,d,e) -> lambda args: a(b(c(d(e(*args)))))

Upvotes: 2

Views: 137

Answers (3)

HennyH
HennyH

Reputation: 7944

This works with multiple input values so you can have lambdas which all take N paramters, and return N values.

def F(*funcs):
    def _(*arg):
        if len(arg) ==  1:
            arg = arg[0]
            for f in reversed(funcs):
                arg = f(arg)
        else:
            for f in reversed(funcs):
                arg = f(*arg)
        return arg
    return _

Test (multiple):

a = lambda n,m: (n + m,m)
b = lambda n,m: (n*m,n)
print(F(a,b)(1,2))
>>> 
(3, 1)

Test (single):

a = lambda n: n + n
b = lambda n: n ** 2
print(F(a,b)(1))
>>> 
2

Upvotes: 1

jamylak
jamylak

Reputation: 133544

a = lambda n: n + 2
b = lambda n: n * 2
def F(*funcs):
    def G(*args):
        res = funcs[-1](*args)
        for f in funcs[-2::-1]:
            res = f(res)
        return res
    return G

>>> F(a, b)(1)
4

Or better with reduce like @DanielRoseman

def F(*funcs):
    def G(*args):
        return reduce(lambda x, y: y(x), funcs[-2::-1], funcs[-1](*args))
    return G

>>> F(a, b)(1)
4

You could even do it in a single line but I feel like it's less elegant:

def F(*funcs):
  return lambda *args: reduce(lambda x, y: y(x), funcs[-2::-1], funcs[-1](*args))

Upvotes: 2

Daniel Roseman
Daniel Roseman

Reputation: 599580

You probably want reduce: maybe something like:

reduce(lambda x, y: y(x), [a, b, c, d, e], initial_value)

Upvotes: 2

Related Questions