Skip to content
Advertisement

Weird nested Python lambda

How does this python lambda work?

lambda v1: (lambda v2: v1(v2(v2)))(lambda v3: v1(lambda v4: v3(v3)(v4)))

My understanding:

  1. The lambda v3: v1(lambda v4: v3(v3)(v4)) becomes the argument v1, and the statement becomes lambda v2: v1(v2(v2)) with v1 binding to the lambda v3: v1(lambda v4: v3(v3)(v4))
  2. But what is the status of v1 in lambda 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.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement