Схема/ракетка: выполнять порядок оценки оценки
-
02-10-2019 - |
Вопрос
Следующая процедура действительна как в схеме 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)
в этом случае) будет оцениваться по порядку. Если это не гарантировано, то моя процедура не очень стабильная.
Я ничего не видел, указав это в стандартах ни одного языка, но я спрашиваю здесь, потому что, когда я проверил, это было провалено в порядке.
Решение
Они, как правило, не гарантированно оцениваются по порядку, но результат будет таким же. Это потому, что здесь нет побочных эффектов-петля не меняется 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
Call не заставляет его делать что -то другое.
Наконец, обратите внимание, что при оценке ракетки является Гарантированно будет слева направо. Это имеет значение, когда есть побочные эффекты-ракетка предпочитает предсказуемое поведение, тогда как другие возражают против этого, утверждая, что это заставляет людей кодировать это неявно полагается на это. Общий небольшой пример, который показывает разницу:
(list (read-line) (read-line))
который в ракетке гарантированно вернет список прочтения первой строки, а затем второй. Другие реализации могут вернуть две строки в другом порядке.