2

我正在 Linux 上试用 m4 CLI 并尝试创建一个 for(begin, end, step) 宏,该宏将打印出给定范围内的逗号分隔的数字列表。我还希望它支持默认步骤 1。我尝试了以下

[tom@sp4 ~]$ m4
define(`for',`ifelse($#,2,`for($1,$2,1)',eval($1+$3>$2),1,$1,`$1, for(eval($1+$3),$2,$3)')')

for(3,9)
m4:stdin:3: bad expression in eval: 3+>9
3, 4, 5, 6, 7, 8, 9

虽然它工作正常,但我不明白为什么我会收到错误消息,因为 $3 在第一次通过时只是空白。当 $#==2 时,为什么还要费心阅读 eval($1+$3>$2)?

编辑:使用威廉在他的回答中给我的信息,我想出了下面的宏。它接受 0 到 3 个参数,并允许倒数和倒数。我从弄乱这个例子中学到了很多东西。

[tom@sp4 ~]$ m4
define(`for',
    `ifelse(
        $#,0,``for'',
        eval($#==1 && $1+0>0),1,`for(1,$1,1)',
        $#,1,,
        $#,2,`for($1,$2,ifelse(eval($1+0>$2+0),1,-1,1))',
        eval($3+0==0 || $3+0>0 && $1+0>$2+0 || $3+0<0 && $1+0<$2+0),1,,
        eval($1+0+($3+0)ifelse(eval($3+0<0),1,<,>)$2+0),1,$1,
        `$1, for(eval($1+$3),$2,$3)'dnl
    )'dnl
)


for
for
for(0)

for(5)
1, 2, 3, 4, 5                
for(5,-23,-5)
5, 0, -5, -10, -15, -20                    
for(5,9)
5, 6, 7, 8, 9                
for(6,1)
6, 5, 4, 3, 2, 1                    
4

1 回答 1

1

m4遇到 时foo(3,9),它将其扩展ifelse为宏中定义的文本。为了调用ifelse,它必须向它传递参数。要确定这些论点,它必须扩展eval. 因此出现错误消息。

您可以通过以下方式避免错误消息:

define(`for',
`ifelse(
        `$#', `2', `for(`$1', `$2', `1')',
        eval(`$1' + ifelse(`$3', `', `0', `1') > `$2'), `1', `$1',
        `$1, for(eval(`$1' + `$3'), `$2', `$3')'dnl
)')dnl
于 2021-09-25T11:31:39.930 回答