我写了一个小的 m4 脚本 ( test.m4) 用于测试目的:
define(`test', `ifelse(`$#', `1', `$1', test(shift($@)))')
test(`arg1', `arg2')
Run Code Online (Sandbox Code Playgroud)
并用m4 test.m4 -t test -de1运行它。输出是
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(`')))
.
.
.
Run Code Online (Sandbox Code Playgroud)
直到由于超出递归限制而中止执行。我想知道为什么会这样,因为实际上1并且1应该比较相等并且if else宏应该评估为`'.
但是,我有一个创新的想法,将[not-equal]放入引号中,因此宏看起来像这样:
define(`test', `ifelse(`$#', `1', `$1', `test(shift($@))')')
test(`arg1', `arg2')
Run Code Online (Sandbox Code Playgroud)
瞧,它就像一个魅力(即,arg2与领先的换行符一起打印出来)。
输出(具有相同的调用参数):
NL
m4trace: -1- test -> ifelse(`2', `1', `arg1', `test(shift(`arg1',`arg2'))')
m4trace: -1- test -> ifelse(`1', `1', `arg2', `test(shift(`arg2'))')
arg2
Run Code Online (Sandbox Code Playgroud)
(NL代表“换行”)。
我的结论是:即使要比较的两个字符串实际上相等,预处理器[not-equal]仍然会评估分支。
这有什么特定目的吗?IMO,这只是不直观。或者我错过了什么?
1 -t test打开宏的调试跟踪test。-de将调用的宏的定义添加到调试输出中。
虽然表达式是相等的(除了引号),但它们的执行时间不同(由于引号)。
在第一种情况下,test宏在父代test. 所以你会经历一个递归:测试内部测试内部测试等等。
第二种情况使表达式在 AFTERWARDS 之后执行。所以你没有递归。测试后测试。
“16.3 其他不兼容性”部分:
在这种情况下,禁止宏拥有自己的名称将是一个无用的限制。当然,这为 GNU m4 用户留下了更多的绳索上吊!