2008-04-29 / 16:44 / dave

This works because there is a global variable, fact, that has its value set to the value of the lambda expression. When the variable fact in the body of the function is evaluated to determine which function to invoke, the value is found in the global variable. In some sense using a global variable as a function name is unpleasant because it relies on a global and hence a vulnerable resource—the global variable space.

–Richard Gabriel, The Why of Y [PDF]

(emphasis added)

On reflection, “normal” recursion relying on the global namespace is obvious. So are the potential problems:

> (define fact (lambda (n) (if (< n 2) 1 (* n (fact (- n 1))))))
> (map fact '(0 1 2 3 4))
(1 1 2 6 24)
> (define fact2 fact)
> (map fact2 '(0 1 2 3 4))
(1 1 2 6 24)
> (set! fact (lambda (n) 1000))
> (map fact '(0 1 2 3 4))
(1000 1000 1000 1000 1000)
> (map fact2 '(0 1 2 3 4))
(1 1 2000 3000 4000)
>

Never really thought of it that way before.

That’s not the main point of the paper, of course. It’s really about the derivation of the oft-asked-about Y-Combinator.