S,K,B,C and Y are some famous operators that should be familiar to lambda-calculus nerds.<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;SKI_combinator_calculus" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;SKI_combinator_calculus</a><p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Fixed-point_combinator" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Fixed-point_combinator</a><p>The Y combinator (which is  behind the name for this website) lets you define recursive functions without actually using recursion (the only recursive definition is Y itself, which is often available as a language primitive)<p>A less obfuscated version of the factorial using the y combinator would be this one:<p><pre><code>    fac&#x27; f n = if n == 0 then 1 else f (n - 1)
    fac = y fac&#x27;
</code></pre>
note how fac&#x27; is not recursive and instead calls its &quot;f&quot; parameter when it wants to do a recursive call. The y combinator then ties everything together by passing fac&#x27; to itself.<p>The other obfuscating factor in that program are the S,K,B and C combinators. The purpose of these one is to let you write a program without any variable definitions or lambdas. Notice that when that program finally defines `fact`, it has the form<p><pre><code>   fact = y {some big expression}
</code></pre>
where the big expression only has function applications and references to the previously-defined combinators. There are no mentions to the &quot;f&quot; and &quot;n&quot; variables that we had before. The neat thing about the SK family of combinators is that you can use them to build <i>any</i> function, not just the factorial:<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Combinatory_logic#Completeness_of_the_S-K_basis" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Combinatory_logic#Completeness...</a><p>As for the speed comment, one way to implement lazy evaluation, as found in Haskell, is to compile programs down to those SK combinators and then use <i>graph reduction</i> to evaluate the result. I would expect a reasonable Haskell implementation to be able to automatically generate the unreadable combinator version of the program from the usual definition of factorial that we all know and love but maybe there was a Haskell implementation back in 2001 that wasn&#x27;t as reasonable?<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Graph_reduction" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Graph_reduction</a><p><a href="https:&#x2F;&#x2F;en.wikibooks.org&#x2F;wiki&#x2F;Haskell&#x2F;Graph_reduction" rel="nofollow">https:&#x2F;&#x2F;en.wikibooks.org&#x2F;wiki&#x2F;Haskell&#x2F;Graph_reduction</a><p><a href="https:&#x2F;&#x2F;wiki.haskell.org&#x2F;Super_combinator" rel="nofollow">https:&#x2F;&#x2F;wiki.haskell.org&#x2F;Super_combinator</a><p>That said, dunno how the more recent Haskell compiler handle things. Hopefully some other helpful HN-er can enlighten us here.