方案/球拍:进行循环评估顺序
-
02-10-2019 - |
题
以下过程在方案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))
在球拍中,保证返回第一行读取的列表,然后返回第二行读取的列表。其他实现可能会以不同的顺序返回两行。
不隶属于 StackOverflow