Repeated Function Application - python

I'm having trouble with a question which follows: Write a recursive function repeatedlyApply that takes as arguments a function
f of one argument and a positive integer n. The result of repeatedlyApply is a function of one argument that applies f to that argument n times.
So, for example, we would have
repeatedlyApply(lambda x: x+1,10)(100) ==> 110
You may assume that the following function has been defined. You don't have to use it, but it can contribute to a pretty solution.
def compose(f,g):
return lambda x: f(g(x))
So far i've written this
def compose(f,g):
return lambda x: f(g(x))
def recApply(f,n):
for i in range(n):
return recApply(compose(f,f), n-1)
return f
I'm going wrong somewhere because using the above example recApply(lambda x: x+1,10)(100) i get 1124.
Help much appreciated

Correct answer is:
def recApply(func, n):
if n > 1:
rec_func = recApply(func, n - 1)
return lambda x: func(rec_func(x))
return func
And the output:
>>>> print recApply(lambda x: x+1,10)(100)
110

Your function needs some work:
You have a return inside your for loop, so you return immediately instead of running the loop.
You have a recursive call inside your for loop, so you are doing a bit too much iteration. Choose one or the other.
Be careful when you stack function compositions on top of each other, you are doing power composition rather than linear composition.
Can you tell us what precisely you are trying to do?
EDIT: Since everybody else is posting an answer:
recApply = lambda f, n: lambda x: x if n == 0 else recApply(f, n-1)(f(x))

I have a solution based on lambdas:
>>> f = lambda x: x + 10
>>> iterate = lambda f, n, x : reduce(lambda x, y: f(x), range(n), x)
>>> iterate(f, 10, 3)
103
>>> iterate(f, 4, 4)
44
>>> f10 = lambda x: iterate(f, 10, x)
>>> f10(5)
105

I assume this is an exercise of some sort. There are a few ways you could do it, here's a short one:
>>> repeatedlyApply = lambda f, n: reduce(lambda f1, f2: compose(f1, f2), [f]*n)
>>> repeatedlyApply(lambda x: x+1,10)(100)
110

Related

Combine list of lambdas in a single one

What's the pythonic way to combine a list of lambdas in a single function? For example:
lambdas = [lambda x, k=k: x+k for k in range(3)]
I would like to get this all in a single lambda similar to this but without having to type it out:
f = lambda x: lambdas[2](lambdas[1](lambdas[0](x)))
You can do this with functools.reduce like below:
from functools import reduce
lambdas = [lambda x, k=k: x+k for k in range(3)]
# x = 0
reduce(lambda x, l: l(x), lambdas, x)
# -> l[2](l[1](l[0](x)))
# step_1 : x = x , l = lambda[0] -> lambda[0](x)
# step_2 : x = lambda[0](x), l = lambda[1] -> lambda[1](lambda[0](x))
# step_3 : x = lambda[1](lambda[0](x)), l = lambda[2] -> lambda[2](lambda[1](lambda[0](x)))
The reduce function is defined to be exactly what you want. An alternative is to use a simple for loop.
def f(x):
for func in lambdas:
x = func(x)
return x
to do this with a lambda seems kind of weird.
Is there any specific reason why we cannot:
def function_chainer(lambdas):
def chained(x):
for function in lambdas:
x = function(x)
return chained
This solution is not a one-liner, but it is pythonic I believe.
If you really need a one-liner, you can use functools.reduce:
lambda x: functools.reduce(lambda a, f: f(a), lambdas, x)
The first argument to reduce governs the way of applying each subsequent element, the second is the iterable (here - our iterable of lambdas) and the last one is the initializer - the first value we want to pass to those lambda functions.

How does lambda inside lambda function work?

When I try to print and see what each function does, I'm able to call only the h function. All others return functions.
Also, can anybody tell me why this code prints 13 and what is happening?
two_to_one = lambda g: (lambda y: g(y,y))`
one_to_two = lambda f: (lambda x, y: f(x) + f(y))
h = one_to_two(two_to_one(lambda x, y: x*y))
print(h(3,2))
That was quite a mind bender!
So let's just break the logic bit by bit. We'll start from h, it is essentially
h = lambda x, y : x*x + y*y
h(3,2) # output is 13
Now, we'll be good programmers and look for repetition. x*x and y*y are essentially the same thing. Why not have a lambda that does that?
a = lambda x: x*x
h = lambda x,y: a(x) + a(y)
h(3,2)
Good, but I want the caller to decide whether to do x*x or x**x or x+x. Everytime I do that I dont want to change a. So I instead pass a lambda to a with whatever operation I want to perform
# a is just a delegator now. It just calls the lambda that it is "initialized" with passing the values twice
a = lambda lambdaIAmPassing: (lambda someValue: lambdaIAmPassing(someValue, someValue))
# lets pass a multiplication lambda
mul_a = a(lambda x,y: x*y)
# lets pass a addition doing lambda
add_a = a(lambda x,y: x+y)
h = mul_a(3) + mul_a(2)
print h #output is 13
h = add_a(3) + add_a(2)
print h # output is 10
Is this clear? You would have realized now that a is in fact the lambda two_to_one in your question
Now the final step.Do you see any other repetition in the code? we are calling mul_a twice and add_a twice. So to avoid this we define a lambda that calls whatever function is passed to it twice - once per parameter - and adds up the values
# Lambda that adds up the result of the function call
lambda_adder = lambda f: (lambda value1, value2: f(value1) + f(value2))
"Initialize" this lambda with mul_a
h = lambda_adder(mul_a)
h(3,2) # output is 13
Hence we end up with the code in your question
two_to_one = lambda g: (lambda y: g(y,y))
This equals a function which calls a function g, passing it two variables, both y. In this case, g is
lambda x, y: x*y
because that is the argument passed to two_to_one on the third line (h's assignment).
one_to_two = lambda f: (lambda x, y: f(x) + f(y))
This equals a function which returns the sum of two calls to the function f, passing the values x and y. In this case, f is the two_to_one function.
Breaking it down:
first = lambda x, y: x*y
second = lambda y: first(y,y)
third = lambda x, y: second(x) + second(y)
simplifies to:
second = lambda y: y * y
third = lambda x, y: second(x) + second(y)
simplifies to:
third = lambda x, y: x * x + y * y
So, what the code is doing is returning the sum of the squares of the arguments. In this case, they are 3 and 2.
I hope it will be relatively easy to follow.
two_to_one = lambda g: (lambda y: g(y,y))
two_to_one is a function, with an input of a function (g: a function with an input of two parameters (as seen in g(y,y)), and output of a function (with 1 input y, and output of g(y,y)). Meaning it is a function of functions. So when giving two_to_one a two parameter function g, you get back a function, that takes 1 number and outputs g(y,y).
e.g:
two_to_one(lambda x,y:x+y)(3)
6
We gave two_to_one a function that gets two numbers and output their sum, lambda x,y:x+y, and we got back a function that takes 1 number and output its sum with itself two_to_one(lambda x,y:x+y). So with an input of 3 it outputs 6.
Second line is similiar:
one_to_two = lambda f: (lambda x, y: f(x) + f(y))
Take a function f (of 1 parameter - due to f(x)), and give back a function, that gets two parameters (numbers probably) x,y and outputs f(x) + f(y).
Now, for the 13 output - working from inner to outer:
h = one_to_two(two_to_one(lambda x, y: x*y))
lambda x, y: x*y two parameter input - output of multiplication. This is the input of two_to_one so (remember what was written earlier) two_to_one(lambda x, y: x*y) is a function that gets 1 number, and returns it squared. And finally, feeding this function to one_to_two gives a function that gets two numbers (those x,y frim before) and returns their sum of squares.
In total h(3,2) gives 3**2+2**2=13.

Python lambda expression compose iterator script

I'm writing a python script that should take a list of functions, written as lambda expressions, and return the compose of all the function, but, I have an arrow in the script, maybe because of the way I'm using lambda expression. It seems like even after I give the returned function a number value, I get back a function, and not a number. This is what I've wrote:
def compose1(lst):
if lst == []:
return lambda x: x
else:
temp = (lst[len(lst)-1])
for i in range(len(lst)-2,-1,-1):
temp = lambda x: lst[i](temp)
return lambda x: temp
this is a tast for the function I've wrote, which says I have a mistake.
f = compose1([lambda x: x+1, lambda x: x*2, lambda x: x-1])
for x in range(10):
assert (f(x) == 1 + (x - 1) * 2)
f = compose1([lambda x: x-1, lambda x: x*2, lambda x: x+1])
for x in range(10):
assert (f(x) == (x + 1) * 2) - 1
I would apreciate some halp on this problem..
thanks :)
def compose(*funcs):
"""
compose(func[,...[, func]]) -> function
Return the composition of functions.
For example, compose(foo, bar)(5) == foo(bar(5))
"""
if not all(callable(func) for func in funcs):
raise TypeError('argument must be callable')
funcs = funcs[::-1]
def composition(*args, **kwargs):
args = funcs[0](*args, **kwargs)
for func in funcs[1:]:
args = func(args)
return args
return composition
f = compose(*[lambda x: x+1, lambda x: x*2, lambda x: x-1])
for x in range(10):
assert f(x) == (1 + (x - 1) * 2)
f = compose(*[lambda x: x-1, lambda x: x*2, lambda x: x+1])
for x in range(10):
assert f(x) == ((x + 1) * 2) - 1
It looks like your loop is just reimplementing what reduce does. Here's a functional look at your function composition problem:
def compose1(fnlist):
if not fnlist:
return lambda x: x
# compose 1 function of x from two others
def compose2fns(fn1, fn2):
return lambda x : fn1(fn2(x))
# or if you really love lambdas
# compose2fns = lambda fn1,fn2: lambda x: fn1(fn2(x))
# use reduce to cumulatively apply compose2fns to the functions
# in the given list
return reduce(compose2fns, fnlist)
This passes your tests just fine.
CODE GOLF:
I couldn't resist, here is a one-liner, even including your check for an empty input list:
compose1 = lambda fnlist: reduce(lambda fn1,fn2: lambda x : fn1(fn2(x)),
fnlist or [lambda x:x])
Your issue here is your logic.
for i in range(len(lst)-2,-1,-1):
temp = lambda x: lst[i](temp)
return lambda x: temp
This will set temp to a function. lst is a list of functions, lst[i] is a function. You call that, to give a value, and then you make a new function with lambda. You then return a function that gives that function.
Your return value is a function, that gives a function, that gives a value, hence your issue.
As a note, this code has other problems. if lst == []: should be if not lst:, for example. You should also never iterate by index, and instead iterate by value, as Python is designed. I can't actually work out what you are trying to achieve with your code, which shows how hard to read iterating by index is.
Your code currently does this:
If there are no values, return a function that returns the first argument.
If there is one value, return the function in the list.
If there are many values, return a function that returns a function that returns the first value retrieved by running the first function from the list.
I'm not sure what you were trying to do, but I'm pretty sure that isn't it.
I like this syntax:
f = do (lambda x: x-1) (lambda x: x*2) (lambda x: x+1)
for x in range(10):
assert f(x) == 1 + (x - 1) * 2
The implementation is surprisingly trivial:
class do(object):
def __init__(self, x):
self.fns = [x]
def __call__(self, x):
if callable(x):
self.fns.append(x)
return self
for f in self.fns:
x = f(x)
return x

function making

Hi I am new to functional programming. What i did is
>>> g=lambda x:x*2
>>> f=g
>>> g=lambda x:f(f(x))
>>> g(9)
36
Now, it is not creating g as a nonterminating recursive function - g(x) is transformed to a new function which gives the result g(g(x)).
>>> f=g
>>> g=lambda x:f(f(x))
>>> f(8)
RuntimeError: maximum recursion depth exceeded
I expected g to be transformed into a function which gives the result g(g(g(x))), according to the first definition of g(x). Why does it not? Is it possible to make a new function which results in g(g(g(...(g(x))....))) for a certain number of iterations in this way?
When you do f = g for the second time, f becomes lambda x: f(x). Closures are created by name, not by value.
This becomes easy with a helper function:
def compose(f, g):
return lambda x: f(g(x))
square = lambda x:x*2
g = square
for i in xrange(4):
g = compose(g, square)
In python, variables are names mapped to values, not values themselves (everything is a reference). Also, you can think of lambda as storing text that can be evaluated. The following will illustrate
a = 2
f = lambda x: a*x
f(2) # This gives 4
a = 3
f(2) # This gives 6
This should clear up why you are getting infinite recursion.
In answer to your question about recursing, here is a little hack that might do
g = lambda x, n: n > 0 and g(x, n-1)**2 or x
Then g(2,3) would be (((2)^2)^2)^2 = 256.
This
g=lambda x:x*2
f=g
g=lambda x:f(x)
is equivalent to:
f=lambda x:x*2
g=lambda x:f(x)
When you call g, you get whatever f happens to be defined in the global (or enclosing) scope.
what you're expecting is something like:
f=lambda x:x*2
g=lambda x, f=f:f(x)
That captures the value of f in the outer scope at the time the lambda expression is evaluated.

recursive lambda-expressions possible?

I'm trying to write a lambda-expression that calls itself, but i can't seem to find any syntax for that, or even if it's possible.
Essentially what I wanted to transfer the following function into the following lambda expression: (I realize it's a silly application, it just adds, but I'm exploring what I can do with lambda-expressions in python)
def add(a, b):
if a <= 0:
return b
else:
return 1 + add(a - 1, b)
add = lambda a, b: [1 + add(a-1, b), b][a <= 0]
but calling the lambda form of add results in a runtime error because the maximum recursion depth is reached. Is it even possible to do this in python? Or am I just making some stupid mistake? Oh, I'm using python3.0, but I don't think that should matter?
Maybe you need a Y combinator?
Edit - make that a Z combinator (I hadn't realized that Y combinators are more for call-by-name)
Using the definition of the Z combinator from Wikipedia
>>> Z = lambda f: (lambda x: f(lambda *args: x(x)(*args)))(lambda x: f(lambda *args: x(x)(*args)))
Using this, you can then define add as a completely anonymous function (ie. no reference to its name in its definition)
>>> add = Z(lambda f: lambda a, b: b if a <= 0 else 1 + f(a - 1, b))
>>> add(1, 1)
2
>>> add(1, 5)
6
Perhaps you should try the Z combinator, where this example is from:
>>> Z = lambda f: (lambda x: f(lambda *args: x(x)(*args)))(lambda x: f(lambda *args: x(x)(*args)))
>>> fact = lambda f: lambda x: 1 if x == 0 else x * f(x-1)
>>> Z(fact)(5)
120
First of all recursive lambda expressions are completely unnecessary. As you yourself point out, for the lambda expression to call itself, it needs to have a name. But lambda expressions is nothing else than anonymous functions. So if you give the lambda expression a name, it's no longer a lambda expression, but a function.
Hence, using a lambda expression is useless, and will only confuse people. So create it with a def instead.
But yes, as you yourself discovered, lambda expressions can be recursive. Your own example is. It's in fact so fantastically recursive that you exceed the maximum recursion depth. So it's recursive alright. Your problem is that you always call add in the expression, so the recursion never stops. Don't do that. Your expression can be expressed like this instead:
add = lambda a, b: a > 0 and (1 + add(a-1, b)) or b
Which takes care of that problem. However, your first def is the correct way of doing it.
add = lambda a, b: b if a <= 0 else 1 + add(a - 1, b)
You want the Y combinator, or some other fixed point combinator.
Here's an example implementation as a Python lambda expression:
Y = lambda g: (lambda f: g(lambda arg: f(f)(arg))) (lambda f: g(lambda arg: f(f)(arg)))
Use it like so:
factorial = Y(lambda f: (lambda num: num and num * f(num - 1) or 1))
That is, you pass into Y() a single-argument function (or lambda), which receives as its argument a recursive version of itself. So the function doesn't need to know its own name, since it gets a reference to itself instead.
Note that this does get tricky for your add() function because the Y combinator only supports passing a single argument. You can get more arguments by currying -- but I'll leave that as an exercise for the reader. :-)
a little late ... but I just found this gem # http://metapython.blogspot.com/2010/11/recursive-lambda-functions.html
def myself (*args, **kw):
caller_frame = currentframe(1)
code = caller_frame.f_code
return FunctionType(code, caller_frame.f_globals)(*args,**kw)
print "5! = "
print (lambda x:1 if n <= 1 else myself(n-1)*n)(5)

Categories