samedi 23 avril 2016

Why is the "wrong" expression of an ifelse macro evaluated anyway?

I wrote a small m4 script (test.m4) for testing purposes:

define(`test', `ifelse(`$#', `1', `$1', test(shift($@)))')
test(`arg1', `arg2')

and ran it with m4 test.m4 -t test -de1. The output was

m4trace: -1- test -> ifelse(`2', `1', `arg1', test(shift(`arg1',`arg2')))
m4trace: -2- test -> ifelse(`1', `1', `arg2', test(shift(`arg2')))
m4trace: -3- test -> ifelse(`1', `1', `', test(shift(`')))
m4trace: -4- test -> ifelse(`1', `1', `', test(shift(`')))
.
.
.

until execution was aborted due to an exceeded recursion limit. I wondered why this was so because actually 1 and 1 should compare equal and the if else macro should evaluate to `'.

However, I had the innovative idea to put the [not-equal] into quotation marks, so the macro looked like this:

define(`test', `ifelse(`$#', `1', `$1', `test(shift($@))')')
test(`arg1', `arg2')

and voilà, it worked like a charm (i.e., arg2 was printed out along with a leading newline).
The output (with the same invocation parameters):

NL
m4trace: -1- test -> ifelse(`2', `1', `arg1', `test(shift(`arg1',`arg2'))')
m4trace: -1- test -> ifelse(`1', `1', `arg2', `test(shift(`arg2'))')
arg2

(NL stands for "newline").

My conclusion: even though the two strings to compare are, in fact, equal, the preprocessor evaluates the [not-equal] branch nevertheless.

Does this have any specific purpose? IMO, it's just unintuitive. Or am I missing something?


1 -t test turns debug tracing for the macro test on. -de adds the definition of an invoked macro to the debugging output.

Aucun commentaire:

Enregistrer un commentaire