DrRacket 中的 While 循环宏 [英] While Loop Macro in DrRacket

查看:17
本文介绍了DrRacket 中的 While 循环宏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to create a macro for while loop in DrRacket. Here is what I wrote:

(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))))

这个程序的输出是:

0
1
2
3
4
5
6
7
8
9
error:  procedure application: expected procedure, given: #<void>; arguments were: #<void>

有人可以帮我解决这个问题吗?为什么这个宏不直接终止并返回 void.似乎当 condition 不为真时,系统会尝试将 void 作为参数应用到某个过程.

Can someone help me with this? Why wouldn't this macro just terminate and return void. It seems that when the condition is not true, the system tries to apply the void as an argument to some procedure.

推荐答案

哎哟:

  1. 使用这种风格的 while 循环会鼓励过度使用命令式编程.
  2. 使用 define-macro 会创建不卫生的宏,这在 Scheme 中是一场噩梦.
  1. Using this style of while loop encourages excessive use of imperative programming.
  2. Using define-macro creates unhygienic macros, which is a nightmare in Scheme.

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

While I don't encourage writing an imperative-style loop macro, for your reference, here's a non-define-macro version of the same macro:

(define-syntax-rule (my-while condition body ...)
  (let loop ()
    (when condition
      body ...
      (loop))))

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

It uses syntax-rules, which creates hygienic macros, and is much, much easier to read than what you have.

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

Now, for the actual answer for your question, first, let's write your original macro out in a more readable way:

(define-macro my-while
  (lambda (condition body)
    `(local ((define (while-loop)
               (if ,condition
                   (,body (while-loop))
                   (void))))
       (while-loop))))

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

Once you write it out this way, you can see where the real problem is: in the (,body (while-loop)) line, which should instead have been (begin ,body (while-loop)).

这篇关于DrRacket 中的 While 循环宏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆