2012-02-16 50 views
2

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

(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只采取一个单一的论点,但这里似乎需要两个。

想到这里发生了什么?

回答

11

这不是一个for循环,这是一个名为let。它所做的是创建一个名为for的函数,然后调用它; “循环”行为是由函数中的递归引起的。调用函数loop更符合惯用,顺便说一句。例如。

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

被这实际上不是使用for语言功能,但只是使用let的变化,让您轻松地编写递归函数扩展到像

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

非常感谢,我按照你所描述的扩展了命名的let,现在对我更有意义。 – 2012-02-16 15:11:20

5

。请参阅this关于let的文档(它是那里的第二种形式)。

这是怎么回事的是,这let形式结合它传递的名称(在这种情况下for)与给定的参数列表(timesval)的程序,并与初始值调用它。正文中绑定名称的使用是递归调用。

底线:for在这里并不重要。这只是一个名字。你可以将它重命名为foo,它仍然可以工作。球拍有确实的循环,你可以阅读关于here