I couldn't understand the Y-combinator, so I tried to implement a function that enabled recursion without native implementation. After some thinking, I ended up with this:
Y = λx.(λv.(x x) v)
Which is shorter than the actual one:
Y = λf.(λx.f (x x)) (λx.f (x x))
And, for my surprise, worked. Some examples:
// JavaScript
Y = function(x){
return function(v){
return x(x, v);
};
};
sum = Y(function(f, n){
return n == 0 ? 0 : n + f(f, n - 1);
});
sum(4);
; Scheme
(define Y (lambda (x) (lambda (v) (x x v))))
(define sum (Y
(lambda (f n)
(if (equal? n 0)
0
(+ n (f f (- n 1)))))))
(sum 4)
Both snippets output 10 (summation from 0 to 4) as expected.
What is this, why it is shorter and why we prefer the longer version?
The reason it is shorter is that what you implemented is not the Y combinator. It's something that is between the actual Y combinator, and something that is sometimes known as a U combinator. To be a proper Y combinator, this should work:
(define sum
(Y (lambda (f)
(lambda (v) (if (equal? n 0) 0 (+ n (f (- n 1))))))))
or in Javascript:
sum = Y( function(f) { return function(n) {
return n == 0 ? 0 : n + f(n-1);
};});
If you work your way to something that makes that work, you'll find that one thing that will make it longer is that you need to move the duplicated f
thing into the Y, and the next thing that makes it even longer is when you end up protecting the x x
self-application inside a function since these language are strict.
The difference from the "real" version is that you do need to pass your own function along with the parameters, which you usually don't need to - Y does abstract over that by giving your function the recursice variant of itself.
Sum in JavaScript should be just
Y (function(rec){ return function (n) { return n==0 ? 0 : n + rec(n-1); };})
I understood the Y combinator when I restructured the common JS expression to
function Y (f) {
function alt (x) {
function rec (y) { // this function is basically equal to Y (f)
return x(x)(y); // as x === alt
}
return f (rec);
}
return alt(alt);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With