Related
So, the standard factorial function in python is defined as:
def factorial(x):
if x == 0:
return 1
else:
return x * factorial(x-1)
Since n! := n * (n-1) * ... * 1, we can write n! as (n+1)! / (n+1). Thus 0! = 1 and we wouldn't need that if x == 0. I tried to write that in python to but I didn't work. Can you guys help me?
Since this is a recursive function (return x * factorial(x-1)) you must have an end condition (if x == 0:).
It is true that n! == (n+1)! / (n+1) and you could change your recursive call to :
def factorial(x):
return factorial(x+1) / (x+1)
But that again would have no end condition -> endless recursion (you will calling the next (n+1)! and than the (n+2)! and so on forever (or until you'll get an exception)).
BTW, you can have the condition stop your execution at 1:
if x == 1:
return 1
You wouldn't want to use recursive function for things that are not limited, hence I suggest doing a little bit importing from the standard library
from functools import reduce
import operator
def fact(x):
if not isinstance(x, int) or x <= 0:
raise Exception("math error")
else:
return reduce(operator.mul, range(1, x + 1), 1)
print(fact("string"))
print(fact(-5))
print(fact(0))
print(fact(5))
Just realized that there is no need for a hustle like that:
def fact2(x):
if not isinstance(x, int) or x <= 0:
Exception("math error")
else:
y = 1
while x > 1:
y *= x
x -= 1
return y
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)
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:]
I have a vector of a few hundred numerical entries (like this: Xo = [x1, y1, x2, y2,..., xN, yN]) where N is an arbitrary number. I need to pass this vector to the scipy fmin_cobyla optimizer with simple simple constraints on each of the entries:
1. All of the x's (ie. x1, x2, ..., xN) are such that -1
I've tried to use lambda functions to specify the constraints like this
b0 = lambda Xo: 1 - Xo[n]
b1 = lambda Xo: Xo[n] + 1
however I am completely unsure of how to pass in the proper index n. I want all the even n to be subject to b0 and b1 but all the odd n to be subject to b2 and b3
b2 = lambda Xo: 2 - Xo[n]
b3 = lambda Xo: Xo[n] + 2
I may need to use consargs in fmin_cobyla. Any help would be much appreciated.
Do the constraints need to be continuous? If not, here's a simple way to do it with one function. It will return 1 if the constraints are met, and -1 if they're not:
def checkall(xs):
for j, x in enumerate(xs):
if abs(x) > (2 if j % 2 else 1):
return -1
return 1
cons = (checkall,)
If you need continuous constraints, there are many ways to do it. Here's one with 2N linear functions, N for the positive constraint, and N for the negative constraints.
def checkpos(j):
if j % 2:
return lambda xs: 2 - xs[j]
else:
return lambda xs: 1 - xs[j]
def checkneg(j):
if j % 2:
return lambda xs: 2 + xs[j]
else:
return lambda xs: 1 + xs[j]
cons = [checkpos(j) for j in range(N)] + [checkneg(j) for j in range(N)]
try this
even = lambda x: (x < 1 and x > -1)
odd = lambda x: (x < 2 and x > -2)
constraint = lambda index: (index % 2) and odd or even
filtered = [x for index, x in enumerate(Xo) if constraint(index)(x)]
Honestly, I have no idea what fmin_cobyla, but this is another try after reading David's comment
even = lambda n: ((lambda x: 1 - x[n]), (lambda x: x[n] + 1))
odd = lambda n: ((lambda x: 2 - x[n]), (lambda x: 2 - x[n]))
constraint = lambda n: (n % 2) and odd(n) or even(n)
constraint_list = sum([constraint(i) for i in range(2 * N)], ())
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).