Tomer Hochbaum
Tomer Hochbaum

Reputation: 67

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))

Upvotes: 1

Views: 2274

Answers (3)

Tzahi T
Tzahi T

Reputation: 356

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.

Upvotes: 0

S Raghav
S Raghav

Reputation: 1526

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

Upvotes: 4

bgfvdu3w
bgfvdu3w

Reputation: 1725

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.

3 * 3 + 2 * 2 = 13

9 + 4 = 13

Upvotes: 2

Related Questions