So I've been messing around with Python a bit lately and I'm trying to find a way to output the nth number of the fibonacci sequence in a single expression. This is the code that I've written so far:
(lambda f: f if f<2 else (f-1)+(f-2))(n)
# n == 1 -> 1
# n == 2 -> 1
# n == 3 -> 3
# n == 4 -> 5
# n == 5 -> 7
....
However, as I commented above this simply outputs a set of odd numbers. I'm confused as to why this is happening because if I am to re-write this as a named lambda function, it would look something like this:
f = lambda n: n if n<2 else f(f-1)+f(f-2)
# f(1) -> 1
# f(2) -> 1
# f(3) -> 2
# f(4) -> 3
...
# f(10) -> 55
...
Now the reason I've added the Lambda Calculus tag is because I'm not sure if this question falls under the domain of simply understanding how Python handles this. I've read a tiny bit about the Y combinator in lambda calculus, but that's a foreign language to me and couldn't derive anything from resources I found for this about lambda calculus.
Now, the reason I'm trying to do this in one line of code, as opposed to naming it, is because I want to try and put this lambda function into list comprehension. So do something like this:
[(lambda f: f if f<2 else (f-1)+(f-2))(n) for n in range(10)]
and create an array of the first x numbers in the fibonacci sequence.
What I'm looking for is a method of doing this whole thing in one expression, and should this fall under the domain of Lambda calculus, which I believe it does, for someone to explain how this would work.
Feel free to offer an answer in JavaScript, C#, or other C-like languages that support Lambda functions.
EDIT: I've found the solution to what I was attempting to do:
[(lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f:(lambda n: n if n<2 else f(n-1)+f(n-2)))(y) for y in range(10)]
I know that this is not at all practical and this method should never be used, but I was concerned with CAN I do this as opposed to SHOULD I ever do this.
You'll need to assign your lambda to an actual variable, and then call the lambda inside the lambda:
>>> g = lambda f: f if f < 2 else g(f-1)+g(f-2)
>>> [g(n) for n in range(10)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
I have a one-line solution that meets your criteria, but it is one of the most crazy codes I ever written. It doesn't use list comprehension, but it mixes dynamic solution and lambda function in one line.
fib = (lambda n: (lambda fib: fib(fib, [], n, None))(lambda fib, arr, i, _: arr if i == 0 else fib(fib, arr, i-1, arr.append(1) if len(arr) < 2 else arr.append(arr[-1]+arr[-2]))))
Just to explain it a bit. The first part (lambda fib: fib(fib, [], n, None)) take a lambda function as parameter and then call it with the parameters it expect. This trick allows us to assign a name to the lambda function and to pass this name to itself.. this is the magic.
Instead second part, the core function, lambda fib, arr, i, _: arr if i == 0 else fib(fib, arr, i-1, arr.append(1) if len(arr) < 2 else arr.append(arr[-1]+arr[-2]))) uses another trick to implement the dynamic solution. The first parameter fib is a reference to itself, the second parameter, arr, is the array containing our solution and it is filled from left to right calling recursively fib exactly n times. The recursion ends when the third parameter i becomes 0. The fourth parameter is an ugly trick: it is not used by the function, but it is used to call the append method of arr.
This is absolutely the less elegant solution, but it is also the fastest one. I report the timings for N=500 below.
The naive solution is unfeasible, but here you can find the code to compute one element at a time of the series (this is probably what you wanted to mix lambda function and recursion):
(lambda n: ((lambda fib: fib(fib,n+1))(lambda fib, i: (1 if i <= 2 else fib(fib,i-2) + fib(fib,i-1)))))(N)
Solution proposed by #cdlane:
%timeit [0, 1] + [(4<<n*(3+n)) // ((4<<2*n)-(2<<n)-1) & ((2<<n)-1) for n in range(N)][1:]
10 loops, best of 3: 88.3 ms per loop
Solution proposed by #lehiester:
%timeit [int(round((lambda n: ((1+5**0.5)**n-(1-5**0.5)**n)/(2**n*5**0.5))(x))) for x in range(N)]
1000 loops, best of 3: 1.49 ms per loop
My ugly solution:
%timeit (lambda n: (lambda fib: fib(fib, [], n, None))(lambda fib, arr, i, _: arr if i == 0 else fib(fib, arr, i-1, arr.append(1) if len(arr) < 2 else arr.append(arr[-1]+arr[-2]))))(N)
1000 loops, best of 3: 434 us per loop
Another ugly and faster solution which doesn't use the recursion:
%timeit (lambda n: (lambda arr, fib_supp: [arr] + [fib_supp(arr) for i in xrange(n)])([], (lambda arr: arr.append(1) if len(arr) < 2 else arr.append(arr[-1]+arr[-2])))[0])(N)
1000 loops, best of 3: 346 us per loop
UPDATE
Finally I found an elegant way to formulate the one-line function. The idea is always the same, but using the setitem method instead of the append. Some of the trick I used can be found at this link. This approach is just a bit slower, but at least is readable:
%timeit (lambda n: (lambda arr, fib_supp: any(fib_supp(i, arr) for i in xrange(2,n)) or arr)([1] * n, (lambda i, arr: arr.__setitem__(i,(arr[i-1]+arr[i-2])))))(N)
1000 loops, best of 3: 385 us per loop
How about:
(lambda f: (4 << f * (3 + f)) // ((4 << 2 * f) - (2 << f) - 1) & ((2 << f) - 1))(n)
It doesn't start the sequence in the usual way:
0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, ...
But once you get past 1, you're fine. You'll find a detailed explanation in the blog entry An integer formula for Fibonacci numbers along with lots of related information.
On my system, #lehiester's golden ratio based solution goes off the rails at F71, producing 308061521170130, instead of 308061521170129 and continues to deviate from there.
lambda calculus via Python
Since this is tagged with lambda-calculus, rather than write an answer that relies on clever tricks or language features that are specific to python, I'm only going to use simple lambdas
U = lambda f: f (f)
Y = U (lambda h: lambda f: f (lambda x: h (h) (f) (x)))
loop = Y (lambda recur: lambda acc: lambda a: lambda b: lambda n:
acc if n == 0 else
recur (acc + [a]) (a + b) (a) (n - 1))
fibonacci = loop ([]) (0) (1)
print (fibonacci (10))
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Of course we used four named lambdas U, Y, loop, and fibonacci – because each lambda is a pure function, we can replace any reference to its name with its value
# in Y, replace U with its definition
Y = (lambda f: f (f)) (lambda h: lambda f: f (lambda x: h (h) (f) (x)))
# in loop, replace Y with its definition
loop = (lambda f: f (f)) (lambda h: lambda f: f (lambda x: h (h) (f) (x))) (lambda recur: lambda acc: lambda a: lambda b: lambda n:
acc if n == 0 else
recur (acc + [a]) (a + b) (a) (n - 1))
# in fibonacci, replace loop with its definition
fibonacci = (lambda f: f (f)) (lambda h: lambda f: f (lambda x: h (h) (f) (x))) (lambda recur: lambda acc: lambda a: lambda b: lambda n:
acc if n == 0 else
recur (acc + [a]) (a + b) (a) (n - 1)) ([]) (0) (1)
fibonacci is now a single, pure expression – we could call the lambda directly in the print statement...
# in print, replace fibonacci with its definition
print ((lambda f: f (f)) (lambda h: lambda f: f (lambda x: h (h) (f) (x))) (lambda recur: lambda acc: lambda a: lambda b: lambda n:
acc if n == 0 else
recur (acc + [a]) (a + b) (a) (n - 1)) ([]) (0) (1) (10))
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
once again, using another program
I wrote a very similar answer (also in Python) but in the context of a different program – it might be useful to help see the generality of the techniques
once again, in another language
We'll do the entire thing again only this time in JavaScript. JS is better suited for the demonstration this exercise because we can show the code working here in the browser and the lambda syntax is much more permissive (in terms of code formatting) – other than that, you'll notice the programs are almost identical
const U = f =>
f (f)
const Y =
U (h => f => f (x => h (h) (f) (x)))
const loop = Y (recur => acc => a => b => n =>
n === 0
? acc
: recur (acc.concat ([a])) (a + b) (a) (n - 1))
const fibonacci =
loop ([]) (0) (1)
console.log (fibonacci (10))
// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
// in Y, replace U with its definition
Y = (f => f (f)) (h => f => f (x => h (h) (f) (x)))
// in loop, replace Y with its definition
loop = (f => f (f)) (h => f => f (x => h (h) (f) (x))) (recur => acc => a => b => n =>
n === 0
? acc
: recur (acc.concat ([a])) (a + b) (a) (n - 1))
// in fibonacci, replace loop with its definition
fibonacci = (f => f (f)) (h => f => f (x => h (h) (f) (x))) (recur => acc => a => b => n =>
n === 0
? acc
: recur (acc.concat ([a])) (a + b) (a) (n - 1)) ([]) (0) (1)
fibonacci is now a single, pure expression – we could call the lambda directly in the console.log statement...
oh and it's really fast, too
console.time ('fibonacci (500)')
console.log ((f => f (f)) (h => f => f (x => h (h) (f) (x))) (recur => acc => a => b => n =>
n === 0
? acc
: recur (acc.concat ([a])) (a + b) (a) (n - 1)) ([]) (0) (1) (500))
console.timeEnd ('fibonacci (500)')
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... 490 more items ]
// fibonacci (500): 3 ms
practice makes perfect
The lambda calculus has been one of my favourite areas of study. With just the Y-combinator alone, I've spent countless hours exploring its beauty and sophistication. I hope you find these explorations helpful. If you have any other questions on the subject matter, don't be shy to ask ^_^
You have to somehow assign a name to it in order to use a recursive definition--otherwise a recursive lambda function is impossible in Python since it doesn't have any special reflexive keyword that refers to it.
As #TerryA mentioned, you could use the trick in this post in order to generate a sequence of x Fibonacci numbers in one statement with the recursive definition.
Or, you could use the closed form, which would be much faster:
[int(round((lambda n: ((1+5**0.5)**n-(1-5**0.5)**n)/(2**n*5**0.5))(x)))
for x in range(10)]
This assumes that x is not very large, though, because the float arithmetic will overflow around x=600 and will probably have large rounding errors before that point--as #cdlane points out, this starts diverging from the actual sequence at x=71, i.e. x in range(72).
EDIT: #cdlane shared a closed form with only integer arithmetic, which should work for any x in theory. I would probably use this one instead of the expression above.
[0, 1] + [(4<<n*(3+n)) // ((4<<2*n)-(2<<n)-1) & ((2<<n)-1)
for n in range(10)][1:]
Related
In church numerals, if we have:
# (define zero (lambda (f) (lambda (x) x)))
zero = lambda f: lambda x: x
Then the successor function can be defined as:
# (define succ (lambda (n) (lambda (f) (lambda (x) (f ((n f) x))))))
succ = lambda n: lambda f: lambda x: f(n(f)(x))
Maybe this is a silly question, but if the successor essentially adds one more wrapper f(...) to the previous equation, why couldn't this just be defined as f(n)? Is this more for consistency of definition, or why can't that shorter form be used?
(Note: using python definitions here as well as scheme as it makes it a bit simpler for me to test with.)
The numeral n is defined as n applications of the function f to some argument x.
Thus,
0 = λf.λx.x
1 = λf.λx.f x
2 = λf.λx.f (f x)
3 = λf.λx.f (f (f (x))
...
Note that 1 is not the same as λf.λx.f 0, so succ 0 can't be, either. (The same is true for the other numerals.)
Your definition, λn.λf.λx.(f n) would give
succ 0 = (λn.λf.λx.(f n)) (λg.λy.y)
= λf.λx.f (λg.λy.y)
which is not the same as 1, but
(λn.λf.λx.f (n f x)) (λg.λy.y)
= λf.λx.f ((λg.λy.y) f x)
= λf.λx.f ((λy.y) x)
= λf.λx.f x
= 1
I'm writing a Higher Order that takes a lambda expression, a number, then number of times it has to repeat that. This is what I have:
#Square Root
sqrt = lambda x: x ** (1/2)
#Repeat
def repeat(f,x,r):
return [f(i) for r in x]
Here's what it should do:
>>> repeat(sqrt, 2, 0)
2
>>> repeat(sqrt, 2, 1)
1.4142135623730951
>>> repeat(sqrt, 2, 2)
1.189207115002721
Here's the error message:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "main.py", line 66, in repeat
return [f(i) for r in x]
TypeError: 'int' object is not iterable
This is NOT a repeat because I am asking how to fix MY code, not how to do the problem. Also this is NOT homework, it is simply a project to understand higher order functions better.
Something like this would work if you used a for loop.
#Square Root
sqrt = lambda x: x ** (1/2)
#Repeat
def repeat(f,x,r):
for i in range(r):
x = f(x)
return x
print(repeat(sqrt, 2, 2))
A list comprehension is not the right tool here. You want a single value — a list comprehension always creates a list.
Since this seems like an exercise, in keeping with the style of lambdas and higher order functions, you could recurse with something like:
sqrt = lambda x: x ** (1/2)
rep = lambda f, x, r: f(x) if r < 1 else f(rep(f, x, r - 1))
rep(sqrt, 2, 0)
# 1.4142135623730951
rep(sqrt, 2, 1)
# 1.189207115002721
If r will be large, you may have issues with recursion depth, however.
You could also use functools.reduce
from functools import reduce
sqrt = lambda x: x ** (1/2)
rep = lambda f, x, r: reduce(lambda n, _: f(n), range(r+1), x)
rep(sqrt, 2, 0)
# 1.4142135623730951
rep(sqrt, 2, 1)
# 1.189207115002721
#Square Root
sqrt = lambda x: x ** (1/2)
#Repeat
def repeat(f,x,r):
if r > 0:
return repeat(f,f(x),r-1)
else:
return x
print(repeat(sqrt, 2, 2))
>> 1.189207115002721
a solution using recursion
def repeat(f,x,r):
return [f(i) for r in range(x)]
You are trying to iterate number which is not possible
I want to create list of lambdas by a given size n (so manual assignment won't work) where each element depends on previous function and it index in the list.
I've tried various stuff like this :
n = 3
func_list = [lambda x : 1]
for k in range(1,n):
func_list.append(lambda x : func_list[k-1](x) * (x+k))
print(list(map(lambda f : print(f(1)), func_list)))
But in all attempts I've got error message about recursion depth:
RecursionError Traceback (most recent call last)
<ipython-input-296-f35123a830c4> in <module>
2 for k in range(1,3):
3 func_list.append(lambda x : func_list[k-1](x) * (x+k))
----> 4 print(list(map(lambda f : print(f(1)), func_list)))
<ipython-input-296-f35123a830c4> in <lambda>(f)
2 for k in range(1,3):
3 func_list.append(lambda x : func_list[k-1](x) * (x+k))
----> 4 print(list(map(lambda f : print(f(1)), func_list)))
<ipython-input-296-f35123a830c4> in <lambda>(x)
1 func_list = [lambda x : 1]
2 for k in range(1,3):
----> 3 func_list.append(lambda x : func_list[k-1](x) * (x+k))
4 print(list(map(lambda f : print(f(1)), func_list)))
... last 1 frames repeated, from the frame below ...
<ipython-input-296-f35123a830c4> in <lambda>(x)
1 func_list = [lambda x : 1]
2 for k in range(1,3):
----> 3 func_list.append(lambda x : func_list[k-1](x) * (x+k))
4 print(list(map(lambda f : print(f(1)), func_list)))
RecursionError: maximum recursion depth exceeded
As Elegant Odoo's answer pointed out, Python lambdas capture variables by reference.
Another term that you might hear when searching for answers is "late binding", which means binding of the variable inside the lambda to its actual value happens only when the lambda is executed. As a results, all lambda functions you've created has the same (and final) value for k, which causes infinite recursion.
While the exec-based approach is valid, I think most people would agree that exec should be avoided in practical code. An alternative solution to this is to create lambda functions via functions to force early binding:
n = 3
func_list = [lambda x: 1]
def create_fn(k_val):
return lambda x: func_list[k_val - 1](x) * (x + k_val)
for k in range(1, n):
func_list.append(create_fn(k))
print(list(map(lambda f: f(1), func_list)))
When you call create_fn with k, the current value of k is passed to the function under the name k_val. The variable k_val in the lambda function is then bound to the k_val variable in the scope of create_fn, with the value of k at the time when it's called.
A very good case to explain the difference between Reference and Value:
Let me explain why this happen to understand what happen lets use
a normal function so we can debug the value of K:
n = 3
func_list = [lambda x : 1]
for k in range(1,n):
def f(x):
print('K is: ', k)
return func_list[k-1](x) * (x + k)
func_list.append(f)
# just print will be enough to cause error
print(func_list[2])
Out puts is:
K is : 2
K is : 2
K is : 2
K is : 2
K is : 2
....
....
....
....
RecursionError: maximum recursion depth exceeded while calling a Python object
You are using the same variable (reference to value) in all methods. K reference to value 2 generated from the loop.
to demonstrate after the end of loop make k = 5, this will raise error index out of range.
A simple solution with exec :
n = 3
func_list = [lambda x: 1]
for k in range(1, n):
# here you are not using variable k we are using the value it's like
# we are rewriting it to code every time but is not you who typing it's the compute -_^
exec('func_list.append(lambda x : func_list[{k}-1](x) * (x + {k}))'.format(k=k))
# lambda print(f(1)) will create [None, None, None] I removed the print
print(list(map(lambda f: f(1), func_list)))
Out put:
[1, 2, 6]
Of curse the solution above work for your case because K is jut a simple Integer
what if K is an very complicated object, with complicated attributes and private
variable. In order to achieve the same thing you need to reconstruct the object.
# we need to consract another object using the value
exec('... KClass({}, {}, {}) ...'.format(k.attr1, k.attr2, k.attr2))
Imaging that KClass uses attribute Object of XClass you will need to construct both object k and x.
SO using exec is not practical a better way to handle this is the Factory Pattern:
n = 3
func_list = [lambda x: 1]
def method_factory(k):
# here K reference it's not the same K reference that is created
# in loop there are different but with the alias K
return lambda x: func_list[k - 1](x) * (x + k)
for k in range(1, n):
func_list.append(method_factory(k))
print(list(map(lambda f: f(1), func_list)))
Why this work because when you call method_factory this will create its own scope that contain
a reference with alias K that point to the same value that reference K of loop points to.
Hope you got the idea it's all about reference and scopes.
here is the recursion code I am trying to change it to tail recursion
def stairClimb(n):
if n <= 3:
WaysToClimb = [1, 2, 4]
return WaysToClimb[n - 1]
else:
return stairClimb(n - 1) + stairClimb(n - 2) + stairClimb(n - 3)
When a procedure can recur multiple times per procedure application, to achieve a tail call, we must somehow sequence the multiple recursive calls
Using a technique called continuation-passing style, we can add a second parameter to our function that tells our function what the next step of our computation should be
A simple CPS conversion looks like this
def my_func (x):
return x
def my_cps_func (x, k)
# k represents the "next step"
return k (x)
Python has neat features tho, so we can write our function to support both direct style and continuation-passing style. We do this by assigning a default function as the continuation – we'll use this technique more below, so make sure you understand it here first
# by default, pass x thru untouched
# this is known as the "identity" function
def add (x, y, k = lambda x: x):
return k (x + y)
# direct style
print (add (2, 3)) # 5
# continuation-passing style
add (2, 3, print) # 5
# direct and CPS mixed! invent your own freedom
print (add (2, 3, lambda sum: add (sum, sum))) # 10
Your stair_climb is like a 3-fibonacci procedure (sometimes called "tribonacci") only yours uses a unique (1,2,4) seed instead of a more traditional (0,0,1) seed – we'll show tribonacci converted to CPS then we'll look at your procedure after that
def tribonacci (n, k = lambda x: x):
if n == 0:
return k (0)
elif n == 1:
return k (0)
elif n == 2:
return k (1)
else:
return tribonacci (n - 1, lambda a:
tribonacci (n - 2, lambda b:
tribonacci (n - 3, lambda c:
k (a + b + c))))
for x in range (1,10):
print (tribonacci (x))
# 0
# 1
# 1
# 2
# 4
# 7
# 13
# 24
# 44
But the time complexity of that function is O (3n) - since lambdas can abstract any number of values, this can be massively optimized by using a multi-parameter lambda – here we compute the same answer in O (n) where lambda a, b, c: ... represents our "seed"
# by default, return the first value of the seed
def tribonacci (n, k = lambda a, b, c: a):
if n == 0:
# base seed values
return k (0, 0, 1)
else:
# the next seed (this is our "next step")
return tribonacci (n - 1, lambda a, b, c:
# new seed
# b is the "next a"
# c is the "next b"
# the sum of each is the "next c"
k (b, c, a + b + c))
for x in range (1,10):
print (tribonacci (x))
# 0
# 1
# 1
# 2
# 4
# 7
# 13
# 24
# 44
All we have to do is change the k (0, 0, 1) seed to k (1, 2, 4)
def stair_climb (n, k = lambda a, b, c: a):
if n == 0:
return k (1, 2, 4)
else:
return stair_climb (n - 1, lambda a, b, c:
k (b, c, a + b + c))
for x in range (1,10):
print (stair_climb (x))
# 2
# 4
# 7
# 13
# 24
# 44
# 81
# 149
# 274
And yep, if you look at each line, every procedure application is in tail position
def stair_climb (n, k = lambda a, b, c: a):
if n == 0:
# tail
return k (1, 2, 4)
else:
# tail
return stair_climb (n - 1, lambda a, b, c:
# tail
k (b, c, a + b + c))
But you have a bigger problem – Python doesn't have tail call elimination
print (stair_climb (1000))
# RecursionError: maximum recursion depth exceeded in comparison
No worries, once you're using continuation-passing style, there's all sorts of ways around that
use accumulator:
def stairClimb(n, acc, acc1, acc2):
if n == 3:
return acc2
else:
return stairClimb(n-1, acc1, acc2, acc+acc1+acc2)
and call it with the initial numbers:
stairClimb(n, 1, 2, 4)
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?
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!
without reduce, map, named lambdas or python internals:
(lambda a:lambda v:a(a,v))(lambda s,x:1 if x==0 else x*s(s,x-1))(10)
Contrary to what sth said, you CAN directly do this.
(lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))(n)
The first part is the fixed-point combinator Y that facilitates recursion in lambda calculus
Y = (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))
the second part is the factorial function fact defined recursively
fact = (lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))
Y is applied to fact to form another lambda expression
F = Y(fact)
which is applied to the third part, n, which evaulates to the nth factorial
>>> n = 5
>>> F(n)
120
or equivalently
>>> (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))(5)
120
If however you prefer fibs to facts you can do that too using the same combinator
>>> (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: f(i - 1) + f(i - 2) if i > 1 else 1))(5)
8
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],
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)
This answer is pretty basic. It is a little simpler than Hugo Walter's answer:
>>> (lambda f: f(f))(lambda f, i=0: (i < 10)and f(f, i + 1)or i)
10
>>>
Hugo Walter's answer:
(lambda a:lambda v:a(a,v))(lambda s,x:1 if x==0 else x*s(s,x-1))(10)
We can now use new python syntax to make it way shorter and easier to read:
Fibonacci:
>>> (f:=lambda x: 1 if x <= 1 else f(x - 1) + f(x - 2))(5)
8
Factorial:
>>> (f:=lambda x: 1 if x == 0 else x*f(x - 1))(5)
120
We use := to name the lambda: use the name directly in the lambda itself and call it right away as an anonymous function.
(see https://www.python.org/dev/peps/pep-0572)
def recursive(def_fun):
def wrapper(*p, **kw):
fi = lambda *p, **kw: def_fun(fi, *p, **kw)
return def_fun(fi, *p, **kw)
return wrapper
factorial = recursive(lambda f, n: 1 if n < 2 else n * f(n - 1))
print(factorial(10))
fibonaci = recursive(lambda f, n: f(n - 1) + f(n - 2) if n > 1 else 1)
print(fibonaci(10))
Hope it would be helpful to someone.
By the way, instead of slow calculation of Fibonacci:
f = lambda x: 1 if x in (1,2) else f(x-1)+f(x-2)
I suggest fast calculation of Fibonacci:
fib = lambda n, pp=1, pn=1, c=1: pp if c > n else fib(n, pn, pn+pp, c+1)
It works really fast.
Also here is factorial calculation:
fact = lambda n, p=1, c=1: p if c > n else fact(n, p*c, c+1)
Well, not exactly pure lambda recursion, but it's applicable in places, where you can only use lambdas, e.g. reduce, map and list comprehensions, or other lambdas. The trick is to benefit from list comprehension and Python's name scope. The following example traverses the dictionary by the given chain of keys.
>>> data = {'John': {'age': 33}, 'Kate': {'age': 32}}
>>> [fn(data, ['John', 'age']) for fn in [lambda d, keys: None if d is None or type(d) is not dict or len(keys) < 1 or keys[0] not in d else (d[keys[0]] if len(keys) == 1 else fn(d[keys[0]], keys[1:]))]][0]
33
The lambda reuses its name defined in the list comprehension expression (fn). The example is rather complicated, but it shows the concept.
Short answer
Z = lambda f : (lambda x : f(lambda v : x(x)(v)))(lambda x : f(lambda v : x(x)(v)))
fact = Z(lambda f : lambda n : 1 if n == 0 else n * f(n - 1))
print(fact(5))
Edited: 04/24/2022
Explanation
For this we can use Fixed-point combinators, specifically Z combinator, because it will work in strict languages, also called eager languages:
const Z = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)))
Define fact function and modify it:
1. const fact n = n === 0 ? 1 : n * fact(n - 1)
2. const fact = n => n === 0 ? 1 : n * fact(n - 1)
3. const _fact = (fact => n => n === 0 ? 1 : n * fact(n - 1))
Notice that:
fact === Z(_fact)
And use it:
const Z = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)));
const _fact = f => n => n === 0 ? 1 : n * f(n - 1);
const fact = Z(_fact);
console.log(fact(5)); //120
See also:
Fixed-point combinators in JavaScript: Memoizing recursive functions
I got some homework about it and figured out something, heres an example of a lambda function with recursive calls:
sucesor = lambda n,f,x: (f)(x) if n == 0 else sucesor(n-1,f,(f)(x))
I know this is an old thread, but it ranks high on some google search results :). With the arrival of python 3.8 you can use the walrus operator to implement a Y-combinator with less syntax!
fib = (lambda f: (rec := lambda args: f(rec, args)))\
(lambda f, n: n if n <= 1 else f(n-2) + f(n-1))
As simple as:
fac = lambda n: 1 if n <= 1 else n*fac(n-1)
Lambda can easily replace recursive functions in Python:
For example, this basic compound_interest:
def interest(amount, rate, period):
if period == 0:
return amount
else:
return interest(amount * rate, rate, period - 1)
can be replaced by:
lambda_interest = lambda a,r,p: a if p == 0 else lambda_interest(a * r, r, p - 1)
or for more visibility :
lambda_interest = lambda amount, rate, period: \
amount if period == 0 else \
lambda_interest(amount * rate, rate, period - 1)
USAGE:
print(interest(10000, 1.1, 3))
print(lambda_interest(10000, 1.1, 3))
Output:
13310.0
13310.0
If you were truly masochistic, you might be able to do it using C extensions, but this exceeds the capability of a lambda (unnamed, anonymous) functon.
No. (for most values of no).