Like them devout numbers, the Y combinator is a right of passage for any would-be functional programmer.

No, we're not talking about orange-flavoured racism, we've got some functional fun up our sleeves. I've never really understood the damn thing and I'm excited to try to rectify that.

So, how do it do?

Well, aight, here's the sitch. Say we had a recursive function, like, math's most excited function, the factorial:

var factorial = function(n) { if (n == 0) { return 1; } else { return n * factorial(n-1); } };

Now, here's the game: what if a function couldn't refer to itself in its definition? How could we make recursion work?

Easy! Like any good functional programmer, we make the thing a higher-order function. Simple enough, if a little mind-bending, we can pass the function to itself:

var factorialStep = function(self) { return function(n) { if (n == 0) { return 1; } else { var recur = self(self); return n * recur(n-1); } } }; var factorial = function(n) { return factorialStep(factorialStep)(n); };

Neat! `recur`

is a little tricky here, but it's the next `factorialStep`

, created by threading `self`

through to, well, itself, which returns a function ready to be called with the next `n`

.

Let's clean stuff up a bit though. Ideally, we'd just pass `factorialStep`

the `recur`

function and eschew all the grody details of the implementation. And we can do that by shuffling things around a little:

var factorialStep = function(recur) { return function(n) { if (n == 0) { return 1; } else { return n * recur(n-1); } } }; var factorial = function(n) { var recursionHelper = function(self) { var recur = function(n) { return self(self)(n); }; return factorialStep(recur); }; return recursionHelper(recursionHelper)(n); };

Is this better? Kinda! We'll circle back to that. Check that `recursionHelper`

function though. When called, it returns a `factorialStep`

, passing it a `recur`

method.

`recur`

is tricky again! Remember, `self`

is `recursionHelper`

and when we call it, it returns the next `factorialStep`

. So, when `recur`

is called, it creates another `factorialStep`

and calls it with the next `n`

. Oof, getcher brain around that.

Why's this better? Well, if you peer through the thick fog of FP fugure, you can see that the bulk of `factorial`

can be pulled out and applied to any recursive function. Let's do that! You remember ol' Fibonacci?

var makeRecursive = function(f) { var recursionHelper = (function(self) { var recur = function(n) { return self(self)(n); }; return f(recur); }); return recursionHelper(recursionHelper); }; var factorial = makeRecursive(function(recur) { return function(n) { if (n == 0) { return 1; } else { return n * recur(n-1); } } }); var fibonacci = makeRecursive(function(recur) { return function(n) { if (n <= 1) { return 1; } else { return recur(n-1) + recur(n-2); } } });

We can poke `makeRecursive`

a bit more to bring it in line with society's standards. Let's *Pretty Function* that down-and-out boy.

Remember, another way to name a value is to bind it as a function parameter. So, for example:

var y = 1; console.log(y);

becomes:

(function(y) { console.log(y); })(1);

Applying the same to `makeRecursive`

, this:

var makeRecursive = function(f) { var recursionHelper = function(self) { var recur = function(n) { return self(self)(n); }; return f(recur); }; return recursionHelper(recursionHelper); }

var makeRecursive = function(f) { return (function(recursionHelper) { return recursionHelper(recursionHelper); })(function(self) { var recur = function(n) { return self(self)(n); }; return f(recur); }); };

But huh, those variable names don't make a lotta sense anymore. Let's fix that up and heck, inline `recur`

. We can also generalize things by forwarding all of the arguments, not just `n`

, with `apply`

:

var makeRecursive = function(f) { return (function(x) { return x(x); })(function(x) { return f(function() { return x(x).apply(null, arguments); }); }); };

And that beautiful monstrosity is the Y combinator! Now we can make all sortsa recursive functions! How cool is that!

Yeah, it's pretty opaque just to look at. I dunno, I'm not sure I'd even recognize the damn thing if I passed it on the street, but y'know, the rote, mechanical steps that get us there are each pretty straightforward, if, like, you spend a few hours staring at 'em.