Reputation: 67
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
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
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
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.
Upvotes: 2