Just to get the goods up front:
define(`m4Y', `dnl pushdef(`m4Y_recur',dnl `pushdef(`m4Y_LL',dnl `$1''changequote([,])(['changequote([,])`changequote`]`$[]1'(``$[]1'')dnl ['changequote([,])'changequote`])changequote`dnl (changequote([,])`$[]1'changequote)dnl `popdef(`m4Y_LL')')'dnl `m4Y_LL')dnl pushdef(`m4Y_LL',`dnl m4Y_recur(`m4Y_recur')'changequote([,])(`$[]1')changequote`dnl popdef(`m4Y_recur')`'popdef(`m4Y_LL')')`'dnl '`m4Y_LL')`'dnl
So as seems to be popular, I've been working my way through The Little Schemer over the last few weeks.
And, as is equally common, I ground to a halt at the derivation at the end of Chapter IX, where they spring the Y Combinator on the unsuspecting audience. The best way to understand it is to work through it by yourself, so I thought I would see if you could do one in m4. And it turns out you can, though it's not very pretty!
Clearly what the world needs is to know about it, so I wrote it up, and you can follow the derivation in two essays:
-
Higher-Order Programming in m4, which shows you how to do proper quoting to get macro Currying to work.
-
The Y Combinator in m4, which uses those quoting techniques to do the full derivation of m4Y above.
Beware that m4 may be dangerous for the health of compulsive programmers.