views:

1540

answers:

5

A regular function can contain a call to itself in its definition, no problem. I can't figure out how to do it with a lambda function though for the simple reason that the lambda function has no name to refer back to. Is there a way to do it? How?

+4  A: 

I have never used Python, but this is probably what you are looking for.

Lemmy
+15  A: 

The only way I can think of to do this amounts to giving the function a name:

fact = lambda x: 1 if x == 0 else x * fact(x-1)

or alternately, for earlier versions of python:

fact = lambda x: x == 0 and 1 or x * fact(x-1)

Update: using the ideas from the other answers, I was able to wedge the factorial function into a single unnamed lambda:

>>> map(lambda n: (lambda f, *a: f(f, *a))(lambda rec, n: 1 if n == 0 else n*rec(rec, n-1), n), range(10))
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]

So it's possible, but not really recommended!

Greg Hewgill
`map(lambda n: (lambda f, n: f(f, n))(lambda f, n: n*f(f, n-1) if n > 0 else 1, n), range(10))`
J.F. Sebastian
Useless and fun. That's why I love computing.
e-satis
+7  A: 

You can't directly do it, because it has no name. But with a helper function like the Y-combinator Lemmy pointed to, you can create recursion by passing the function as a parameter to itself (as strange as that sounds):

# helper function
def recursive(f, *p, **kw):
   return f(f, *p, **kw)

def fib(n):
   # The rec parameter will be the lambda function itself
   return recursive((lambda rec, n: rec(rec, n-1) + rec(rec, n-2) if n>1 else 1), n)

# using map since we already started to do black functional programming magic
print map(fib, range(10))

This prints the first ten Fibonacci numbers: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55],

sth
I think I finally understand what the Y combinator is for. But I think that in Python it would generally be easier to just use "def" and give the function a name...
pdc
Funny thing is, your Fibonacci example is a great example of something more naturally done with a generator. :-)
pdc
+2  A: 

If you were truly masochistic, you might be able to do it using C extensions, but to echo Greg (hi Greg!), this exceeds the capability of a lambda (unnamed, anonymous) functon.

No. (for most values of no).

Gregg Lind
+3  A: 

Yes. I have two ways to do it, and one was already covered. This is my preferred way.

(lambda v: (lambda n: n * __import__('types').FunctionType(
        __import__('inspect').stack()[0][0].f_code, 
        dict(__import__=__import__, dict=dict)
    )(n - 1) if n > 1 else 1)(v))(5)
Aaron Gallagher
I don't know Python, but that looks terrible. There's really got to be a better way.
Kyle Cronin
You have to learn to appreciate obsfucated code, man. :(
Aaron Gallagher
+1 for teaching me a new way to abuse Python.
Deestan
nobody - the point is that this looks horrible for a reason. Python isn't designed for it, and it's bad practice (in Python). Lambdas are limited by design.
Gregg Lind
Yeah, +1 for the worst Python code ever. When Perl people say "You can write maintainable code in Perl if you know what you are doing", I say "Yeah, and you can write unmaintainable code in Python if you know what you are doing". :-)
Lennart Regebro