In a previous article, we have shown how one can write recursive functions without using names.

Now, we are going to present the Y combinator.

The Y combinator is one of the most aesthetic idea of computer science. It might not be so practical, but it is really beautiful. (It has some practical usages like recursive memoization.)

The Y combinator is a function that allows to generate recursive functions without using names.

Many articles have been written about the Y combinator. The particularity of the current article is that you - the reader - are going to feel the magic of the Y combinator with your hand.

All the code snippets of this page are live and interactive powered by the klipse plugin:

Live: The code is executed in your browser Interactive: You can modify the code and it is evaluated as you type

The Y combinator in action

The Y-combinator takes the idea presented in our previous article one step further and makes it applicable to any function.

Here is the code of the Y-combinator in ruby :

$Y = ->(f) { ->(x) { x[x] }[->(x) { f[->(y) { x[x][y] }] }] } nil

So much power in just 44 characters (not counting the whitespaces), with no other concepts than function definition and function execution!

Let’s see the Y combinator in action with the factorial function. For that purpose, we need to write the factorial function with a tweak: the recursive call is going to be parameterised. Like this:

$factorial_gen = ->(f) { ->(n) { if (n === 0) then 1 else n * f[n - 1] end } } nil

And now, it’s time for magic:

$Y[$factorial_gen][19]

Obviously, we can write exactly the same code without names, by replacing Y and factorial_gen with their bodies:

->(f) { ->(x) { x[x] }[->(x) { f[->(y) { x[x][y] }] }] }[->(f) { ->(n) { if (n === 0) then 1 else n * f[n - 1] end } }][19]

Please take the time to play with the code above: modify the values, rename the arguments….

Then, please take a pause for a few minutes to contemplate this amazing piece of code.

After that, you have two options:

If you go for option #2, please be kind and share your code in the comments below.