I've undone the lambdas just to make it a little easier to read. Here's the code using nested functions:
def f1(f):
def f2(a):
return a(a)
def f3(b):
def f4(*args):
return b(b)(*args)
return f(f4)
return f2(f3)
This would be equivalent basically to:
f1 = lambda f: (lambda a: a(a))(lambda b: f(lambda *args: b(b)(*args)))
Now let's follow the function calls. First you're going to call f1 with some argument. Then the following is going to happen:
- f2 gets called with f3
- f2 returns f3 called with itself as a parameter
- Now we're inside f3 with b being f3
- f3 return f (the parameter you called f1 with) with f4 as the parameter
- f is a callback that gets called with a function as its only parameter
- If f calls this function then its call will be applied to the result of b called with b. b is f3, so f would essentially be calling the result of f3(f3) which is what f is going to return
Therefore f1 can be reduced to:
def f1(f):
def f3():
def f4(*args):
return f3()(*args)
return f(f4)
return f3()
Now I've come up with a way to call f1 that doesn't end in infinite recursion:
called = False
def g1(func):
def g2(*args):
print args
return None
global called
if not called:
called = True
func(5)
else:
return g2
f1(g1) # prints "(5,)"
As you can see, it uses a global to stop the recursion.
Here's another example that runs trials of a Poisson distribution with lambda (lambda is a parameter to the Poisson distribution, not the lambda operator) of 10:
import random
def g3(func):
def g4(a):
def g5(b):
print a
return a+b
return g5
if random.random() < 0.1:
return g4(1)
else:
return g4(func(1))
f1(g3)
And finally something deterministic, not depending on a global, and actually somewhat interesting:
def g6(func):
def g7(n):
if n > 0:
return n*func(n-1)
else:
return 1
return g7
print f1(g6)(5) # 120
print f1(g6)(6) # 720
I'm sure everyone can guess what this function is, but pretty interesting that you can actually get this strange lambda expression to do something useful.