Cam*_*Cam 3 operator-precedence racket do-loops
以下过程在方案r6rs和Racket中都有效:
;; 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)))
Run Code Online (Sandbox Code Playgroud)
我已经为r6rs和Racket测试了它并且它确实正常工作,但我只知道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]))
Run Code Online (Sandbox Code Playgroud)
转换为命名 - let:
(define (make-nums n)
(let loop ([x n] [lst null])
(if (zero? x)
lst
(loop (- x 1) (cons x lst)))))
Run Code Online (Sandbox Code Playgroud)
并进一步将其转换为辅助函数(这就是命名 - let实际上是):
(define (make-nums n)
(define (loop x lst)
(if (zero? x)
lst
(loop (- x 1) (cons x lst))))
(loop n null))
Run Code Online (Sandbox Code Playgroud)
现在应该清楚的是,在递归loop调用中计算两个表达式的顺序并没有使它做任何不同的事情.
最后,请注意,在Racket评估中保证从左到右.当有副作用时这很重要--Backet喜欢可预测的行为,而其他人反对它,声称这会导致人们对隐含依赖于此的代码.一个显示差异的常见小例子是:
(list (read-line) (read-line))
Run Code Online (Sandbox Code Playgroud)
在Racket中保证返回第一行读取的列表,然后是第二行.其他实现可能以不同的顺序返回两行.
| 归档时间: |
|
| 查看次数: |
2540 次 |
| 最近记录: |