Схема / Ракетка: сделать цикл порядка оценки - PullRequest
3 голосов
/ 15 сентября 2010

Следующая процедура действительна как для схемы 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)))

Я проверил ее как для r6rs, так и для Racket, и она работает должным образом, но я точно знаю это только для DrRacket.

У меня вопрос: если гарантировано , то выражения шага (в данном случае (- x 1) и (cons x lst)) будут оцениваться по порядку.Если это не гарантировано, то моя процедура не очень стабильна.

Я не видел ничего, указывающего это в стандартах для любого языка, но я спрашиваю здесь, потому что, когда я тестировал, это оценивали по порядку..

1 Ответ

7 голосов
/ 15 сентября 2010

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

...