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

查看:123
本文介绍了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天全站免登陆