### 12.1 Decrement and increment operators ¶

Increment and decrement of integers are supported using the builtins `incr` and `decr`:

Builtin: incr(number) ¶
Builtin: decr(number) ¶

  Expand to the numerical value of number, incremented or decremented, respectively, by one. Except for the empty string, the expansion is empty if number could not be parsed.

  The macros `incr` and `decr` are recognized only with parameters.

    incr(`4')
    ⇒5
    decr(`7')
    ⇒6
    incr()
    error→m4:stdin:3: empty string treated as 0 in builtin `incr'
    ⇒1
    decr()
    error→m4:stdin:4: empty string treated as 0 in builtin `decr'
    ⇒-1

It is possible to use `incr` to write a macro that produces a different value each time it is invoked:

Composite: counter([seed]) ¶

  When invoked with one argument, reset the counter to seed (where an empty seed is silently treated like 0), without output. Without arguments, output and increment the internal counter.

    define(`_counter', `-1')dnl
    define(`counter', `ifelse(`$#', `0', `define(`_$0', incr(_$0))_$0`'',
    `define(`_$0', eval(`$1-1'))')')
    ⇒
    counter counter counter
    ⇒0 1 2
    counter(`42')
    ⇒
    counter counter
    ⇒42 43
    counter()counter
    ⇒0

It is worth noting how the implementation treats a default empty string as `0` - this is done by storing one less than seed into the internal counter `_counter`, by using `eval` in a way that works even when `$1` is blank.