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.
And a paper from computational dreamtime (well, 1965 anyway), describing Strachey’s GPM, the original ancestor of m4:
Click to access 225.full.pdf