为什么我将此函数转换为 Racket 宏会生成无限递归?

Why my transformation of this function into a Racket macro is generating an infinite recursion?

我正在尝试了解 Racket 的宏。为此,我为特定目的构建了这个函数:

(define  (while-less-fun max)
  (cond [(< a (- max 1)) 
        (and (begin (set! a (+ a 1)) (print "x") a) (while-less-fun max))]
        [(< a max)
         (begin (set! a (+ a 1)) (print "x") a)]
        [(>= a max)
         (begin (set! a (+ a 1)) (print "x") a)]
        ))

它在 REPL 上按预期工作:

> a
2

> (while-less-fun 7)
"x""x""x""x""x"7

> a
7

我试图在下面的宏中转换上面的函数。我的目标是生成相同的结果:

(define-syntax while-less
  (syntax-rules (do)
    [(while-less maximo do begin-exp)
       (cond [(< a (- maximo 1)) 
         (and begin-exp (while-less maximo do begin-exp))]
        [(< a maximo)
         begin-exp]
        [(>= a maximo)
         begin-exp])]))

预期结果是:

(define a 2)
(while-less 7 do (begin (set! a (+ a 1)) (print "x") a))
(while-less 7 do (begin (set! a (+ a 1)) (print "x") a))

计算第二行将打印“x”5 次并将 a 更改为 7。此外,计算第三行将打印“x”1 次并将 a 更改为8.

不幸的是,这会产生一个无限递归,这让我很吃惊。

我做错了什么?为什么会发生这种无限递归?

我知道当一个函数可以解决问题时,你应该避免写宏。但是,我的方法是否是尝试完成此任务的错误方法?

在第一个 cond 子句中,您使用相同的参数调用“(while-less maximo do begin-exp)”,宏的整个主体将通过调用相同的“(while-less maximo做 begin-exp)",导致循环。

您可以为条件创建通用 while:

(define-syntax while 
  (syntax-rules (do)
    [(while condition do begin-exp)
     (let loop ()
       (when condition
         begin-exp
         (loop)))]))
> (define a 2)

> (while (< a 7) do (begin (set! a (+ a 1)) (print "x") a))
"x""x""x""x""x"

> (while (< a 7) do (begin (set! a (+ a 1)) (print "x") a))

>