I got code from here: https://news.ycombinator.com/item?id=25869596
>>> (
lambda n: (lambda fact: fact(n, fact))(
lambda n, inner: 1 if n == 0 else (n * inner(n - 1, inner))
)
)(5)
120
How does this work? I particularly cannot understand how inner gets value.
This can be written as
def func(n):
def func1(fact):
return fact(n, fact)
def func2(n, inner):
return 1 if n == 0 else (n * inner(n - 1, inner))
return func1(func2)
func(5)
inner is func2, or lambda n, inner: 1 if n == 0 else (n * inner(n - 1, inner)) in your example.
lambda fact: fact(n, fact) get the lambda as a parameter and call it recursively.
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 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.
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)], ())