0

Can we code a recursive lambda in python without assigning it to any variable ?

Like this:

print((lambda x: 1 if x <= 1 else x*self(x-1))(5))

I know that this code won't do anything. Specially the self(x-1). Any idea how to do that?

I just want to print the factorial of 5 in one line using a recursive lambda.

M.barg
  • 31
  • 1
  • 1
  • 3

1 Answers1

0

Short answer: No, Python lambdas were not designed to do that.

Longer answer #1: pass the function in as the first argument to itself.

>>> (lambda f: lambda x: f(f,x))(lambda self, x: 1 if x<=1 else x*self(self, x-1))(5)
120

Get it? No? Let's unpack this.

def save_func(self):
    def call_with_self_and(x):
        return self(self, x)
    return call_with_self_and

@save_func
def factorial(self, x):
    return 1 if x<=1 else x*self(self, x-1)

factorial(5)  # 120

It's the same as the one-liner, but I gave everything names. Lambdas have no way to refer to themselves in Python, but you can pass in the lambda as its own first argument. That's what call_with_self_and() does for you: assuming you already have a self, it calls self(self, x), while only requiring x as an argument. That's the function you want.

And save_func() is the factory function that creates the function you want out of the function you have (almost). It takes the self and returns the call_with_self_and().

The "almost" part is that the function you have needs a tweak, from this:

lambda x: 1 if x <= 1 else x*self(x-1)

To this:

lambda self, x: 1 if x<=1 else x*self(self, x-1)

See what I did there? I passed self in as the first argument to self when recursing.

The search term you're looking for is "Y combinator".


Longer answer #2: Python lambdas were not designed to do that, but we can implement it.

This helper function can give a lambda an explicit recursion parameter.

 def R(f):
     def self(*a,**kw):
         return f(self, *a, **kw)
     return self

Use it like so:

print(R(lambda self, x: 1 if x <= 1 else x*self(x-1))(5))
gilch
  • 10,813
  • 1
  • 23
  • 28