I have no clue how the code executes. This is a question on a practice test.
(lambda x: x(x))(lambda y:4)
The output is 4 but I don't know how the code runs. I think the steps are as follows:
lambda (x) is defined
executes lambda (x)
returns x(lambda(y))
lambda (y) is defined
returns 4
x(4)?
I know step 6 is wrong.
This is a tricky question.
Lambdas are anonymous functions. Let's define them to help you understand what is happening.
# (lambda x: x(x))
def func_1(func):
return func(func)
# (lambda y: 4)
def func_2(y):
return 4
>>> func_1(func_2) # Equivalent to (lambda x: x(x))(lambda y:4)
4
The second function is just a callable that returns the constant value of 4 regardless of the value of y, so func_2(10) and func_2(0) both return 4.
The first function is a callable with itself as the single argument to the function (x(x)). We just saw that the second function is a callable that will return the constant value 4 regardless of the input argument, so func_2(func_2) simply returns 4.
lambda expression works just like an unnamed function (anonymous functions). And works like this:
lambda (1): (2)
(1) are parameters
(2) the return
See:
def square(x):
return x**2
Using lambda expression:
square = lambda x: x**2
>>> square(2)
4
But think about the use, maybe you just want to use an function a few times, why store it? Create an anonymous function! How? running a lambda function:
>>> (lambda x: x**2)(2)
4
See? Not that hard. Let's think together.
(lambda x: x(x))(lambda y:4)
lambda y: 4 is passed to our lambda x function, now x = (lambda y: 4) (crazy thing!). x(x) are equals to (lambda y: 4)((lambda y: 4)). Look! We got an parameter to our first 'y' it is (lambda y: 4)! then the first function are executed, and returns 4. What about the second? It doesn't run, and don't need to run! if you do x(x(x)) the second function will run, but not the third one.
Don't think about "lambda is defined". A lambda is a value, like 4. You don't "define" a 4 - it just is. When evaluating a lambda, just replace its (evaluated) arguments into its body (adding parentheses where neccessary). Work it like a rewriting problem.
(lambda x: x(x))(lambda y:4)
# rewrite all `x` in `x(x)` to `lambda y:4` (two appearances):
(lambda y:4)(lambda y:4)
# rewrite all `y` in `4` to `lambda y:4` (zero appearances):
4
Related
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.
I'm having a bit of trouble understanding how Python treats and evaluates lambdas at runtime.
Iteratively building up an integer
Consider the following code (Python 3.5.2):
x = 0
for iteration in range(3):
x = x + 1
print(x)
As expected, this prints 3. Here is my understanding of the way x changes over 3 iterations:
Initial Value: x
Iteration 1: x+1
Iteration 2: (x+1) + 1
Iteration 3: ((x+1) + 1) + 1
Iteratively building up a lambda
Consider the following code:
add3 = lambda x: x
for iteration in range(3):
add3 = lambda x: add3(x) + 1
print(add3(0))
Here is my understanding of the way add3 should change over 3 iterations:
Initial Value: lambda x: x
Iteration 1: lambda x: (lambda x: x)(x) + 1
Iteration 2: lambda x: (lambda x: (lambda x: x)(x) + 1)(x) + 1
Iteration 3: lambda x: (lambda x: (lambda x: (lambda x: x)(x) + 1)(x) + 1)(x) + 1
Instead, calling add3 causes the maximum recursion depth to be exceeded.
My first thought was that Python is dynamically looking up the function body from its name at call time, rather than storing the function's code as part of the function. However, even the following code does not work:
functionList = [lambda x: x] #Store each iteration separately
for i in range(3):
oldFunction = functionList[-1]
newFunction = lambda x: oldFunction(x) + 1 #Should be a completely new lambda object
functionList.append(newFunction)
print(functionList[-1](0)) #Causes infinite recursion
Even with no named functions whatsoever, and following the suggestion here (although I may have misunderstood his answer), it still fails:
functionList = [lambda x: x]
for i in range(3):
functionList.append(lambda x, i=i: functionList[-1](x) + 1)
print(functionList[-1](0)) #Causes infinite recursion
The four lambdas contained in functionList are completely separate objects in memory:
>>> print(functionList)
[<function <lambda> at 0x00000266D41A12F0>, <function <lambda> at 0x00000266D41D7E18>, <function <lambda> at 0x00000266D41D7730>, <function <lambda> at 0x00000266D41D7840>]
Could someone please explain this behavior?
This behavior has nothing to do with 'iterational' lambda generation. When you say add3 = lambda x: add3(x) + 1, the add3 object is replaced with a lambda calling itself recursively with no termination condition.
So when you call add3(0), it becomes:
add3(0) = add3(0) + 1 = (add3(0) + 1) + 1 = ((add3(0) + 1) + 1) + 1
And this goes on forever (well, until the maximum recursion depth is exceeded).
As for other examples, the second function in your list already fails with RecursionError: maximum recursion depth exceeded.
I've got this code for you:
import copy
flist=[lambda x: x]
flist.append(lambda x: copy.deepcopy(flist[-1])(x) + 1)
>>> flist
[<function <lambda> at 0x101d45268>, <function <lambda> at 0x101bf1a60>]
So we made sure that we call a copy of a function. flist[-1](0) results in a RecursionError, and the error is raised in the deepcopy module. So, this means that copy.deepcopy(flist[-1])(x) means 'copy the last element currently in the list and run the copy'.
Here it is: the last element of the list calls itself over and over again.
You are correct that it is evaluated at run time. Because of that, add3, when referenced in itself, is calling itself, not the old add3. In the case of your loop, you are always using [-1]. Since it is evaluated at run time, the first one calls the one at the end of the list. The one at the end of the list then calls the one at the end of the list which calls the one at the end of the list... The list is not changing by the time the functions are being called. Therefore, the first function is called once, and then the last function is called infinitely. What you want is to use [i] instead of [-1]. It is very good that you used a default argument for i in your lambdas because default arguments are evaluated at definition.
Python allows you to access variables in the enclosing scope, but you are changing those variables during the loop.
add3 = lambda x: x
for iteration in range(3):
# This add3 will call itself!
# It always uses the *current* value of add3,
# NOT the value of add3 when it was created.
add3 = lambda x: add3(x) + 1
print(add3(0))
You will need to create a new binding:
add3 = lambda x: x
for _ in range(3):
add3 = (lambda f: lambda x: f(x) + 1)(add3)
print(add3(0))
This creates a new scope each time through the loop, which lets you bind with the current value of add3 rather than the future value of add3.
Languages which behave the way you describe are somewhat rare. Haskell is one example of such a language. In C++ you could achieve this by implicitly copying the lambdas using [=] for the capture list. Python just doesn't do this without some extra work.
Here's how add3 actually changes throughout the loop:
Initial Value: lambda x: x
Iteration 1: lambda x: add3(x) + 1
add3 is not immediately substituted inside the lambda body! It gets looked up when the function is executed.
Iteration 2: lambda x: add3(x) + 1 again
Iteration 3: still lambda x: add3(x) + 1
At the end, when you call add3, the recursive call to add3 inside the lambda body looks up the current value of add3, not the value when the lambda was defined. add3 calls itself, which calls itself, which calls itself, and so on until stack overflow.
Your attempted fix doesn't work because oldFunction still gets looked up at function execution time, so it still finds the final oldFunction instead of the oldFunction from function definition time. You didn't do anything to change that.
For comparison, when you do x = x + 1, x is immediately substituted, so in the first version, the values of x are successively 0, 1, 2, and 3. You don't have x = ((x+1) + 1) + 1 at the end; you just have x = 3.
Except for the name and name binding, the expression lambda <args>: <expression> creates a function that equals the result of def f(<args>): return <expression>. The statement f = lambda <args>: <expression> does not even have the name binding difference. However, some people falsely assume other differences. Many puzzles with lambda are illuminated by replacing it with equivalent defs. For the code above, we get the following.
def add3(x): return x
for iteration in range(3):
def add3(x): return add3(x) + 1
print(add3(0))
Does this make it more obvious that the second def negates the first, by rebinding add3 to a new function object? And that executing the second def statement more than once is redundant? Is it still a surprise that a recursive function with no terminal base case to stop it raises Recursion Error?
Please help me to understand how this works. Output is 4
a=4
b=7
x=lambda: a if 1 else b
lambda x: 'big' if x > 100 else 'small'
print(x())
First, let's remove this line as it doesn't do anything:
lambda x: 'big' if x > 100 else 'small'
This lambda expression is defined but never called. The fact that it's argument is also called x has nothing to do with the rest of the code.
Let's look at what remains:
a = 4
b = 7
x = lambda: a if 1 else b
print(x())
Here x becomes a function as it contains code. The lambda form can only contain expressions, not statements, so it has to use the expression form of if which is backward looking:
true-result if condition else false-result
In this case the condition is 1, which is always true, so the result of the function x() is always the value of a, assigned to 4 earlier in the code. Effectively, x() acts like:
def x():
return a
Understanding the differences between expressions and statements is key to understanding code like this.
Your x is always equals to 4, as it takes no arguments and if 1 is always True.
Then you have lambda expression that's not assigned to any variable, neither used elsewhere.
Eventualy, you print out x, which is always 4 as I said above.
P.S. I strongly suggest you to read Using lambda Functions from Dive into Python
Let me translate that for you.
You assign to x a lambda function with no arguments. Because 1 always evaluates as true, you always return the externally defined variable a, which evaluates as 4.
Then, you create a lambda function with one argument x, which you don't assign to a variable/access name, so it is lost forever.
Then, you call function x, which always returns a. Output is 4.
lambda xxx: foo(xxx) - is it the totally same as just foo?
used in construction like
map(lambda xxx: foo(xxx), my_things)
I dont see any difference:
def plus(a):
return a+1
for i in map(plus, [1,2,3]):
print(i)
for i in map(lambda a: plus(a), [1,2,3]):
print(i)
prints the same
2
3
4
No, lambda x: foo(x) is not the same as foo(x) but rather foo. The eta reduction is the conversion of lambda x: foo(x) to foo.
map(lambda a: plus(a), [1,2,3]) and map(plus, [1,2,3]) are related by replacing lambda a: plus(a) with plus an application of the eta reduction rule.
Yes, that's right. lambda x: foo(x) is the same as just calling foo(x).
Remember that a lambda is just an anonymous function that does something to x. In this case, it just calls foo on x and returns the result of foo(x).
For example, calling (lambda x: foo(x), 60) is similar to doing this:
def function2(y):
return y*2
def function1(x):
return function2(x)
function1(60)
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)