Они, как правило, не гарантируются, чтобы быть оцененными по порядку, но результат будет тем же.Это связано с тем, что здесь нет побочных эффектов - цикл не изменяется 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
незаставьте его делать что-то другое.
Наконец, обратите внимание, что в оценке Racket равен гарантированно слева направо.Это важно, когда есть побочные эффекты - Racket предпочитает предсказуемое поведение, тогда как другие возражают против этого, утверждая, что это приводит людей к коду, который неявно полагается на это.Типичный небольшой пример, показывающий разницу:
(list (read-line) (read-line))
, который в Racket гарантированно возвращает список прочитанной первой строки, а затем второй.Другие реализации могут возвращать две строки в другом порядке.