问题描述
我试图在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.
推荐答案
哦:
- 使用这种样式的
while
循环鼓励过度使用命令式编程. - 使用
define-macro
会创建不卫生的宏,这是Scheme中的噩梦.
- Using this style of
while
loop encourages excessive use of imperative programming. - 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循环宏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!