This explains how the M4 ``loop'' in Learn to Count from One to Ten in Different Languages works. For convenience, and since the code is so short (not to mentions the fact that The Powers That Be deciding in their infinite wisdom that languages weren't for computers and got their grubby BIG hands on everything), here it is again:

define(`_count',`$1
ifelse(`$1',`$2',,`_count(incr(`$1'),`$2')')')dnl
define(`count',`_count(1,$1)')dnl
count(10)dnl

First we define the macro _count. It takes 2 arguments, with the first not larger than the second, and counts from the first to the second. M4 macro arguments live in the placeholders $1,$2,... so first we just output $1 and a newline; this ``just happens'' if we write $1 followed by a newline, since all M4 ever does is expand macros.

The next step is to loop if necessary. M4 has a powerful conditional construct named ifelse (see also [how to say else if). Here we use the form ifelse(A,B,C,D), which expands to C if A and B are equal strings, else to D. If $1 and $2 are the same, we've finished counting, so we make the ifelse expand to nothing; M4 finishes processing the input at that point. Otherwise, we expand to another call to _count, with the start value incremented.

The quotes around the entire ``recursive'' call to _count are absolutely necessary! Without them, the call would take place before the ifelse is evaluated, and we'd immediately get an infinite loop.

Finally, count just tells _count to start counting at 1. The dnls are there to suppress spurious newlines.

Clean, elegant, simple. It's a wonder M4 isn't used more often!

Log in or register to write something here or to contact authors.