How does this python lambda work?
lambda v1: (lambda v2: v1(v2(v2)))(lambda v3: v1(lambda v4: v3(v3)(v4)))
My understanding:
- The
lambda v3: v1(lambda v4: v3(v3)(v4))
becomes the argumentv1
, and the statement becomeslambda v2: v1(v2(v2))
withv1
binding to thelambda v3: v1(lambda v4: v3(v3)(v4))
- But what is the status of
v1
inlambda v3: v1(lambda v4: v3(v3)(v4))
? An reference to itself?
Advertisement
Answer
You can usually figure out things like this (at least simpler versions of this) by converting it into standard functions and breaking it apart:
f1 = lambda v1: (lambda v2: v1(v2(v2)))(lambda v3: v1(lambda v4: v3(v3)(v4)))
becomes
def f1(v1): f2 = lambda v2: v1(v2(v2)) f3 = lambda v3: v1(lambda v4: v3(v3)(v4)) return f2(f3)
becomes
def f1(v1): def f2(v2): return v1(v2(v2))) def f3(v3): def f4(v4): return v3(v3)(v4) return v1(f4) return f2(f3)
So f1
has two major parts. It defines two functions, which I’ve called f2
and f3
. Then it calls f2
with f3
as the argument and returns the result. The argument to f1
, v1
, is visible to both of these functions.
We might be able to talk abstractly about what f2
and f3
do, but since they’ll only be called once, it might be simpler to turn them into more straightforward code that runs directly instead of being defined as a function.
The previous block can be turned into this by replacing f2(f3)
with equivalent code:
def f1(v1): def f3(v3): def f4(v4): return v3(v3)(v4) return v1(f4) return v1(f3(f3))
Note that with this definition of f3
, r = f3(f3)
is equivalent to the following, where we replace the outer call with the internal code of f3
:
# equivalent to r = f3(f3): v3 = f3 def f4(v4): return v3(v3)(v4) r = v1(f4)
which, with some renaming, is equivalent to
def f(v): return f3(f3)(v) r = v1(f)
So anytime we see f3(f3)
, we can replace it with v1(f)
, with f
defined as shown here.
If we make the same substitution for f3(f3)
inside the f(v)
function itself, we get
def f(v): return v1(f)(v) r = v1(f)
Substituting this for f3(f3)
in the definition of f1
gives
def f1(v1): def f(v): return v1(f)(v) return v1(v1(f))
So unless I’ve made a mistake, f1
is a function that accepts another function v1
as its parameter. v1
should be a function that accepts another function as its parameter and returns a function. Then f1
will define this odd little function f
and pass it to v1
. It will take the result of that (another function) and pass it to v1
again. Then it will return the result of that (presumably another function). The nature of that function depends on the v1
function that you pass to f1
when you call it.