在DrRacket中循环宏

Raj*_*hat 3 macros scheme racket

我正在尝试在DrRacket中为while循环创建一个宏.这是我写的:

(require mzlib/defmacro)

(define-macro my-while
  (lambda (condition  body)
    (list 'local (list (list 'define (list 'while-loop)
                             (list 'if condition
                                   (list body (list 'while-loop))
                                   '(void))))
          '(while-loop))))


(define x 0)

(my-while (< x 10)
          (begin              
            (display x)
            (newline)
            (set! x (+ x 1))))
Run Code Online (Sandbox Code Playgroud)

该程序的输出是:

0
1
2
3
4
5
6
7
8
9
error:  procedure application: expected procedure, given: #<void>; arguments were: #<void>
Run Code Online (Sandbox Code Playgroud)

有人可以帮我弄这个吗?为什么这个宏不会终止并返回void.似乎当条件不为真时,系统会尝试将void作为参数应用于某个过程.

Chr*_*ung 7

哎哟:

  1. 使用这种while循环方式会鼓励过度使用命令式编程.
  2. 使用define-macro创建不卫生的宏,这是Scheme中的噩梦.

虽然我不鼓励编写命令式循环宏,供您参考,但这define-macro是同一个宏的非版本:

(define-syntax-rule (my-while condition body ...)
  (let loop ()
    (when condition
      body ...
      (loop))))
Run Code Online (Sandbox Code Playgroud)

它使用syntax-rules,创建卫生的宏,并且比你拥有的更容易阅读.


现在,对于您的问题的实际答案,首先,让我们以更易读的方式编写您的原始宏:

(define-macro my-while
  (lambda (condition body)
    `(local ((define (while-loop)
               (if ,condition
                   (,body (while-loop))
                   (void))))
       (while-loop))))
Run Code Online (Sandbox Code Playgroud)

一旦你用这种方式写出来,你就可以看出真正的问题所在:(,body (while-loop))在行中,应该是这样的(begin ,body (while-loop)).