0

在 GNU M4 中,我一直在尝试编写一个函数来确定有多少非空(不等于的参数`')传递给它。

它应该可以像这样调用:

ne_nargs(0, `1', `')
# 1

ne_nargs(0, `')
# 0

ne_nargs(0, `1')
# 1

请注意,第一个参数应始终为0.

这是我到目前为止的代码:

define(`ne_nargs', `ifelse(`$#', `1`, $1,
   `ifelse(`$2', `', `pushdef(`$2', $1)ne_nargs(shift($@))',
     `pushdef(`$2', incr($1))ne_nargs(shift($@))')')')

这是它的伪代码:

if (number_of_args == 1); then
  return first_arg; // which is `0` by default.
else if (second_arg == ''); then
  second_arg = first_arg;
  return ne_nargs(shift(all_args));
else
  second_arg = (++first_arg);
  return ne_nargs(shift(all_args));

ne_nargs(`0', `', `1', `i', `', `l')

# what I get
m4:test.m4:8: empty string treated as 0 in builtin `incr'
m4:test.m4:8: empty string treated as 0 in builtin `incr'
1

# what I expect
3

我无法弄清楚我在定义中做错了什么ne_nargs,并且在尝试了几种不同的方法来抽象宏的部分之后,我准备放弃了。

4

1 回答 1

1

我认为您不应该尝试覆盖$@;您可以从警告中看到,覆盖 $2 绝对不会影响$@. 文档中的连接示例改为将第二个参数移出:

`$0(`$1', shift(shift($@)))'

所以以下工作:

define(`ne_nargs', `ifelse(`$#', `2', `ifelse(`$2', `', `$1', incr(`$1'))',
  `ifelse(`$2', `', `$0(`$1', shift(shift($@)))',
    `$0(incr($1), shift(shift($@)))')')')
ne_nargs(`0', `', `1', `i', `', `l')

(我不知道清理递归调用的好方法,因此不必独立检查 2 参数调用,因此如果您担心 DRYness,这可能需要改进。)

于 2014-12-30T16:13:19.823 回答