for-loop - 在Scheme中定义For循环

标签 for-loop scheme lisp define-syntax

注意:这似乎是 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/

相关文章:

JavaScript:从 PHP 脚本中提取信息

C++ 指针/for 循环混淆

emacs - emacs lisp中空列表的乘法

lisp - 从命令行与本地长期运行的 Common Lisp 图像交互,可能是守护进程

lisp - CCL 突破文件/目录名称中的非法字符?

javascript - 转储 JQuery 对象

java - 为什么不能反向打印?

scheme - Racket - 最简洁的列表理解方式?

scheme - 查找调用许多过程的过程的增长顺序

lisp - 使用 html5-parser 和 xmls Common Lisp 浏览网页