以下过程在方案R6R和球拍中都是有效的:

;; 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)))

我已经对R6R和球拍进行了测试,并且确实可以正常工作,但是我只知道Drracket肯定。

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

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

有帮助吗?

解决方案

通常不能保证按顺序评估它们,但是结果仍然相同。这是因为这里没有副作用 - 循环不会改变 x 或者 lst, ,它只是将它们重新定为新值,因此评估两个步骤表达式的顺序是无关紧要的。

要查看这一点,请从您的代码的清洁版本开始:

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

翻译成一个名字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 通话不会使它做任何不同的事情。

最后,请注意,在球拍评估中 保证从左到右。当有副作用时,这很重要 - 球拍更喜欢可预测的行为,而其他人则反对它,声称这会导致人们采取隐式依赖这一点的代码。显示区别的一个常见示例是:

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top