注意:这似乎是Gauche Scheme版本0.9.3.3 我似乎无法围绕这些Lisp语言:/。
我正在尝试在Scheme中定义for循环语法。我不确定这是否可以用递归函数(我认为是),但此时我真的想让define-syntax
工作。
我可以使用以下代码运行一次循环(然后看起来它会终止):
(define-syntax forloop
(syntax-rules ()
((forloop start stop exps)
(letrec ((aloop (lambda (astart astop aexps)
(if (<= astart astop) (begin aexps (aloop (+ astart 1) astop aexps))))))
(aloop start stop exps)))))
能够用省略号定义它会很好,但这会给“模板包含重复的常量形式”。我已经阅读了R5RS规范的宏部分,但我很快将重新阅读模板部分:
(define-syntax forloop
(syntax-rules ()
((forloop start stop exps ...)
(letrec ((aloop (lambda (astart astop aexps ...)
(if (<= astart astop) (begin aexps ... (aloop (+ astart 1) astop aexps ...))))))
(aloop start stop exps ...)))))
我首先尝试了这个,但它运行了大约10秒才失败而没有任何输出......我正在使用compileonline.com,所以这可能与它有关:
(define-syntax forloop
(syntax-rules ()
((forloop start stop exps ...)
(if (<= start stop)
(begin exps ... (forloop (+ start 1) stop exps ...))))))
如果我从不调用forloop(我认为是因为它永远不必扩展宏),没有问题,所以我用来测试它们的代码是:
(forloop 6 8 (display "g"))
我做错了什么?我已成功实现when
语句(我自己,但有几十个例子,我已经看过很多)。我认为我想要做的事情和省略号的递归性质让我感到困惑。
答案 0 :(得分:2)
宏在编译时被扩展,因此(begin exps ... (forloop (+ start 1) stop exps ...))
之类的内容会一次又一次地扩展forloop
,无论(+ start 1)
的值是什么(在运行时评估)。 / p>
也许你能做的最好,至少用syntax-rules
,是使用宏来捕获只运行的表达式,并使用非宏代码来处理循环:
(define-syntax forloop
(syntax-rules ()
((forloop start stop exps ...)
(let ((j stop))
(let loop ((i start))
(when (<= i j)
exps ...
(loop (+ i 1))))))))
您还可以使用do
循环:
(define-syntax forloop
(syntax-rules ()
((forloop start stop exps ...)
(let ((j stop))
(do ((i start (+ i 1)))
((> i j))
exps ...)))))