为什么无论如何都要计算 ifelse 宏的"wrong"表达式?



我写了一个小的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')

瞧,它就像一个魅力(即,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将调用的宏的定义添加到调试输出中。

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

在第一种情况下test宏在宏替换父级test期间执行宏。所以你会遇到递归:测试内部测试测试内部测试等等。

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

手册中很好地描述了这种行为。

"16.3 其他不兼容之处"部分:

在像这样的情况下,禁止宏保留自己的名称将是一个无用的限制。当然,这留下了更多 绳索让 GNU m4 用户上吊自杀!

相关内容

  • 没有找到相关文章

最新更新