我正试图编写一个M4宏来生成点图表示法,但我在递归方面遇到了困难。
我想要一个宏,它接受第一个参数,并为所有剩余的参数添加点图关系。例如
coachExisting(a, b, c, d)
将产生
a -> b; a -> c; a -> d;
这是我的尝试:
define(coachExisting, `ifelse(eval($#==2), 1, `ifdef(first, first, $1) -> $2;',
ifelse(eval($#>2), 1,
`ifdef(first, ,define(first, $1)) first -> $2; $0(shift($*))')
)')
然而,这似乎只适用于我使用数字
coachExisting(1, 2, 3, 4)
1 -> 2; 1 -> 3; 1 -> 4;
当我尝试使用字母时,它似乎失去了first
的定义。
coachExisting(a, b, c, d)
b -> b; b -> c; c -> d;
你在快速而松散地引用。有关引用和递归宏评估的指导,请仔细阅读m4手册。在第一个展开中,您得到define(first, $1)
=>define(first, a)
。但在第二次执行时,它扩展为define(first, $1)
=>CCD_ 5=>define(a, b)
(因为first
被扩展为宏(。你需要在任何地方引用first
,所以首先引用define(`first', `$1')'
。
实现宏的一个更干净的方法是从一开始就避免使用临时宏。我推荐这样的东西:
define(`coachExisting', `ifelse(eval($#==2), 1,
`$1 -> $2',
`$1 -> $2; $0(`$1', shift(shift($@)))')')
(不过要小心——我还没有设计这个宏来处理带有0或1参数的情况(。