M4 Macros

January 30, 2015

I decided to write a macro to factor integers. I first wrote this Scheme code, as a model for what I wanted to do; the algorithm is simple trial division:

```> (define (fact n d)
(if (< n (* d d))
(list n)
(if (zero? (modulo n d))
(cons d (fact (/ n d) d))
(fact n (+ d 1)))))
> (define (factors n) (fact n 2))
> (factors 32)
(2 2 2 2 2)
> (factors 35)
(5 7)
> (factors 87463)
(149 587)
> (factors 13290059)
(3119 4261)```

Then I rewrote in `m4`; the only hard part was getting the quoting right:

```\$ m4
define(fact,
`ifelse(eval(\$1 < \$2 * \$2), 1, \$1,
`ifelse(eval(\$1 % \$2 == 0), 1,
\$2 fact(eval(\$1 / \$2), \$2),
fact(\$1, incr(\$2)))')')dnl
define(factors, `fact(\$1, 2)')dnl
factors(32)
2 2 2 2 2
factors(35)
5 7
factors(87463)
149 587
factors(13290059)
3119 4261```

That’s not exactly transparent, though I suppose if you write enough `m4` code you’ll get accustomed to it. Most uses of `m4` are simple substitution, for which it is highly suitable.

You can run the Scheme code at http://programmingpraxis.codepad.org/hAf1OFnz; no `m4` processor is available.