function making - python

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.

Related

How can I convert this for loop pseudocode into Python code without inducing infinite recursion?

I would like to turn the following pseudocode into Python code without inducing infinite recursion.
u(x) = x^2
for i = 0 to 5
v(x) = u(x)^2
u(x) = v(x)
print(u(x))
Here is my attempt, which produces the error "maximum recursion depth exceeded":
import sympy as sym
u = lambda a: a**2
for i in range(0,5):
print('Starting loop',i)
v = lambda b: u(b)**2
u = lambda c: v(c)
print('Ending loop',i)
x = sym.symbols('x')
print(u(x))
Python variables are bound by name, and a for loop does not actually create a new scope. So when you do lambda c: v(c), you are actually creating a function that will look up v from its surrounding scope when its being executed. This means that updates to v are all applied when the function is executed.
In particular, it means that the following two definition already create an infinite loop:
v = lambda b: u(b)**2
u = lambda c: v(c)
Because v calls u, and u calls v. It does not matter that the values are updated later, since the value will be looked up when the function is called.
You can visualize this easily using the following:
>>> x = lambda: y
>>> y = 2
>>> x()
2
>>> y = 5
>>> x()
5
Even though the function x is never updated, it will still use the updated value for y.
What you need here is a closure to put get references to the original functions in a separate scope so that later changes do not affect the function. A simple way is to add another function where the function you want to call is passed as an argument. Since functions create new variable scopes, these will be then independent of the original definitions:
for i in range(0, 5):
print('Starting loop', i)
v = (lambda u: lambda b: u(b)**2)(u)
u = (lambda v: lambda c: v(c))(v)
print('Ending loop', i)
See also this question on how binding works and how closures help there.
Try using these two lines:
v = lambda b, u=u: u(b)**2
u = lambda c, v=v: v(c)
This forces the values of u and v to be captured at the moment of lambda construction. Otherwise, the evaluation will be deferred until the lambdas are invoked.
Here is the complete program:
import sympy as sym
u = lambda a: a**2
for i in range(0,5):
print('Starting loop',i)
v = lambda b, u=u: u(b)**2
u = lambda c, v=v: v(c)
print('Ending loop',i)
x = sym.symbols('x')
print(u(x))
And here is the result:
$ python3 xx.py
Starting loop 0
Ending loop 0
Starting loop 1
Ending loop 1
Starting loop 2
Ending loop 2
Starting loop 3
Ending loop 3
Starting loop 4
Ending loop 4
x**64

Convenient way to add lambda functions together?

Let's say I have this function in a python module:
def functionmaker(a,b):
return lambda x: (a*x) + b
Now let's say I am given a list of this format:
ablist = [[a1, b1], [a2, b2]...[an, bn]] of arbitrary length.
My goal is to add up all the resulting functions you get from these a's and b's.
Of course, with the simple example I gave of ax+b, you could algebraically work it out to being (a1 + a2 + ... an)x + (b1 + b2 + ... bn). But let's ignore that for a moment. The function I am actually working with is a contracted gaussian molecular orbital function, and it's not as easy to trick your way out of the problem with algebra.
What I wanted to do was something like this:
function = lambda x: (a1*x) + b1
q = 2
while q < n:
function = lambda x: function(x) + (ablist[q][0]*x) + ablist[q][1])
q += 1
But it seems you can't call a function inside itself like that. I was hoping it would just over-write the old version of "function" with the new one, but I guess not. I guess I probably need to do some kind of recursive way, but maybe there is a nicer way?
By the way I am using python 2.7.
You can do something like this:
>>> def functionmaker(a, b):
... return lambda x: a*x + b
...
>>> def summer_funcs(args):
... return lambda x: sum(functionmaker(*a)(x) for a in args)
...
>>> arguments = [(1,2), (3,4), (5,6)]
>>> summer_funcs(arguments)(1)
21
Or if you prefer:
>>> f = summer_funcs(arguments)
>>> f(1)
21
>>> f(2)
30
If I've correctly understood your question, you could use the built-in sum() function and pass it a generator expression argument to accomplish the goal:
def functionmaker(a, b):
return lambda x: (a*x) + b
ablist = [(1,2), (3,4), (5,6)]
x = 1
total = sum(functionmaker(a, b)(x) for a, b in ablist)
print(total) # -> 21
If you need to compute this quantity for many different values of x, then it might be worthwhile to optimize things for doing that:
functions = [functionmaker(a, b) for a, b in ablist]
sum_of_functions = lambda x: sum(function(x) for function in functions)
for x in (1, 1.5, 2):
print('sum_of_functions(x={:.1f}) -> {:.1f}'.format(x, sum_of_functions(x)))
Output:
sum_of_functions(x=1.0) -> 21.0
sum_of_functions(x=1.5) -> 25.5
sum_of_functions(x=2.0) -> 30.0

Python: Understanding unfamiliar function syntax (from UC Berkeley CS61A)

I can't do most parts of this question without peeking at the answer key, so I figured I could ask it here. Frankly, I've always had a problem understanding functions with no parameters, and whenever I see one, I think, "OH! they must mean "print" function!" When I'm actually overcomplicating things.
As for Exercise 5, I'm not understanding how to even evaluate the expressions. I feel like it's a simple question, but I can't compute an answer to any of them.
Exercise 4: A Fistful of Functions
For each of the following expressions, what must f be in order for the evaluation of the expression to succeed, without causing an error? Give a definition of f for each expression such that evaluating the expression will not cause an error.
f
f()
f(3)
f()()
f()(3)()
Solution
f = 3
f = lambda: 3
f = lambda x: x
f = lambda: lambda: 3
f = lambda: lambda x: lambda: x
Exercise 5: For A Few Lambdas More
Find the value of the following three expressions, using the given values of t and s.
t = lambda f: lambda x: f(f(f(x)))
s = lambda x: x + 1
t(s)(0) # 1
t(t(s))(0) # 2
t(t)(s)(0) # 3
Solution
1.) 3
2.) 9
3.) 27
For Exercise 4, you are given the following questions and answers.
Q: f
A: f = 3
This is essentially variable assignment.
Q: f()
A: f = lambda: 3
This is similar to a function that takes in no arguments and returns the value 3.
Q: f(3)
A: f = lambda x: x
This is similar to a function that takes in the argument x and returns the value x. So you are given the value 3 and a value of 3 is returned.
Q: f()()
A: f = lambda: lambda: 3
This is similar to a function that takes in no arguments and returns another function that again takes no arguments which will return the value 3.
Q: f()(3)()
A: f = lambda: lambda x: lambda: x
Like the previous example, this will return 3. You have function that takes in no arguments but returns another function that takes in the value x and returns another function that takes in no arguments but returns the value x.
By following the examples above, you can solve Exercise 5 in a similar fashion.
Additionally, Exercise 5 has been explained pretty well in the comments by ChrisP.

Repeated Function Application

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

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