注意:这似乎是 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
语句(我自己,但是有很多例子,我已经见过很多)。我认为我想做的事情的递归性质和省略号把我搞乱了。
最佳答案
宏在编译时扩展,因此类似 (begin exps ... (forloop (+ start 1) stop exps ...))
将扩展 forloop
一次又一次,无论 (+ start 1)
的值是什么(在运行时评估)。
也许您能做的最好的事情,至少对于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 ...)))))
关于for-loop - 在Scheme中定义For循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20810801/