为什么ifelse宏的“错误”表达式仍然被评估?

时间:2016-04-23 20:22:09

标签: if-statement m4

为了测试目的,我写了一个小的m4脚本(test.m4):

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

并使用m4 test.m4 -t test -de 1 运行它。输出是

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(`')))
.
.
.

直到执行因超出递归限制而中止。我想知道为什么会这样,因为实际上11应该相等,而if else宏应该评估为`'

但是,我有创新的想法将[not-equal]放入引号,所以宏看起来像这样:

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

和voilà,它就像一个魅力(即,arg2与一个领先的换行符一起打印出来。)
输出(具有相同的调用参数):

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

NL代表“换行符”)。

我的结论:即使要比较的两个字符串实际上相等,但预处理器仍会评估[not-equal]分支。

这有什么特别的目的吗? IMO,这只是不直观的。或者我错过了什么?

1 -t test打开宏test的调试跟踪。 -de将调用的宏的定义添加到调试输出中。

1 个答案:

答案 0 :(得分:3)

虽然表达式相等(除了引号),但它们的执行时间不同(由于引号)。

在第一种情况下test宏在父代test的宏替换期间执行。所以你经历了一次递归:测试里面的测试,等等。

第二种情况使表达式在AFTERWARDS之后执行。所以你没有递归。测试后测试。

This behaviour is very well described in the manual.

部分" 16.3其他不兼容性":

  

在像这样的情况下,阻止宏拥有自己的名字将是一个无用的限制。当然,这会留下更多   绳索让GNU m4用户自己上吊!