循环如何在计划中运作?

时间:2012-02-16 14:25:25

标签: for-loop scheme racket

我在理解循环如何在方案中工作时遇到一些困难。特别是这个代码运行但我不知道为什么

 (define (bubblesort alist)
  ;; this is straightforward
  (define (swap-pass alist)
    (if (eq? (length alist) 1)
        alist
        (let ((fst (car alist)) (scnd (cadr alist)) (rest (cddr alist)))
          (if (> fst scnd)
              (cons scnd (swap-pass (cons fst rest)))
              (cons fst (swap-pass (cons scnd rest)))))))
  ; this is mysterious--what does the 'for' in the next line do?
  (let for ((times (length alist))
            (val alist))
    (if (> times 1)
        (for (- times 1) (swap-pass val))
        (swap-pass val))))

我无法弄清楚(let for ((应该在这里做什么,而倒数第二行的for表达式也有点偏离 - 我有翻译抱怨for只需要一个参数,但这里似乎需要两个。

对这里发生了什么有任何想法?

2 个答案:

答案 0 :(得分:13)

这不是for循环,而是名为let的。它的作用是创建一个名为for的函数,然后调用它; “循环”行为是由函数中的递归引起的。调用函数loop更加惯用,顺便说一下。 E.g。

(let loop ((times 10))
   (if (= times 0)
     (display "stopped")
     (begin (display "still looping...")
            (loop (- times 1)))))

扩展到类似

的东西
(letrec ((loop (lambda (times)
                 (if (= times 0)
                   (display "stopped")
                   (begin (display "still looping...")
                          (loop (- times 1)))))))
  (loop 10))

答案 1 :(得分:5)

这实际上并没有使用for语言功能,只是使用let的变体,可以让您轻松编写递归函数。请参阅let上的this文档(它是那里的第二个表单)。

正在进行的是这个let形式将它传递的名称(在这种情况下为for)绑定到具有给定参数列表的过程({{1 }和times)并使用初始值调用它。正文中绑定名称的使用是递归调用。

底线:此处val并不重要。它只是一个名字。您可以将其重命名为for,它仍然有效。 Racket确实有关于here的实际for循环。