在Scheme中定义For循环

时间:2013-12-28 03:49:39

标签: 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语句(我自己,但有几十个例子,我已经看过很多)。我认为我想要做的事情和省略号的递归性质让我感到困惑。

1 个答案:

答案 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 ...)))))