Порядок оценки аргументов по стандарту не определен.Вот часть из отчета R6RS :
Примечание: В отличие от других диалектов Лиспа, порядок оценки не указан , иВыражение оператора и выражения операнда всегда оцениваются с использованием одних и тех же правил оценки.
Хотя порядок вычисления в противном случае не определен, влияние любой параллельной оценки выражений оператора и операнда ограничено, чтобы быть совместимым с некоторыми последовательнымипорядок оценки.Порядок оценки может быть выбран по-разному для каждого вызова процедуры.
Вот пример:
(define (debug x)
(display x)
x)
(define (add x y)
(debug (+ (debug x) (debug y))))
(add (add 3 4)
(add 5 6))
; ==> 18
Вот возможные результаты от вызовов display
:
347561171118 ; strictly left to right
651143771118 ; strictly right to left
561134771118 ; ltr in add, rtl in call to add (consistent)
437651111718 ; rtl in add, ltr in call to add (consistent)
В качестве примеров я знаю, что MIT Scheme работает строго справа налево, а DrRacket - слева направо.Икарус сделал третий.
Причина, по которой они недооцениваются, заключается в том, чтобы допустить неизвестную оптимизацию во время написания спецификации.Это не часто порядок важен, особенно если вы пишете это идиоматично.Если вам нужен правильный порядок, вы можете написать его так:
(let ((r1 (read)))
(let ((r2 (read)))
(list 1 r1 2 r2 3)))
Поскольку привязки всегда оцениваются перед тем, как вы будете в безопасности.Это имеет снимок, поэтому вы можете написать его как let*
:
(let* ((r1 (read))
(r2 (read)))
(list 1 r1 2 r2 3))