2010-09-14 75 views
3

的循环顺序以下步骤是在这两个方案R6RS有效和球拍:方案/球拍:不做评价

;; create a list of all the numbers from 1 to n 
(define (make-nums n) 
    (do [(x n (- x 1)) (lst (list) (cons x lst))] 
    ((= x 0) 
    lst))) 

我测试过这两个R6RS和球拍和它正常工作,但我只知道确实为DrRacket。

我的问题是如果它是保证该步骤表达式(在这种情况下(- x 1)(cons x lst))将按顺序进行评价。如果不能保证,那么我的程序不是很稳定。

我没有在任何一种语言的标准中看到任何特定的内容,但我在这里问,因为当我测试它时,它是按顺序排除的。

回答

7

他们通常不保证按顺序评估,但结果仍然是一样的。这是因为这里没有副作用 - 循环不改变xlst,它只是将它们重新绑定到新值,所以两个步骤表达式的评估顺序是不相关的。

看到这一点,与您的代码更清洁的看着版本开始:

(define (make-nums n) 
    (do ([x n (- x 1)] [lst null (cons x lst)]) 
     [(zero? x) lst])) 

翻译为named- let

(define (make-nums n) 
    (let loop ([x n] [lst null]) 
    (if (zero? x) 
     lst 
     (loop (- x 1) (cons x lst))))) 

,并进一步转化,为一个辅助功能(该功能是什么 - let真的是):

(define (make-nums n) 
    (define (loop x lst) 
    (if (zero? x) 
     lst 
     (loop (- x 1) (cons x lst)))) 
    (loop n null)) 

它现在应该清楚,在递归调用loop时评估这两个表达式的顺序并没有使它做任何不同的事情。

最后,请注意,在球拍评估保证是从左到右。当存在副作用时这很重要--Rocket喜欢可预测的行为,而其他人反对,声称这会让人们隐含地依赖于此。示出的差的一个常见小的例子是:

(list (read-line) (read-line)) 

这在球拍保证返回的第一行读出的列表,然后第二个。其他实现可能会以不同的顺序返回这两行。

+0

编辑:谢谢!这很有趣,我没有意识到“做”是这样工作的。 – Cam 2010-09-15 12:21:33