A let
можно переписать как немедленное применение lambda
абстракции
(mylet ([var rhs] ...) body ...) => ((lambda (var ...) body ...) rhs ...)
Обезвоживание c
let
урожайность
(define c ((lambda (d) (set! d (- d 2)) d) 10))
Это просто приложение 10
к функции (которую мы называем f
)
(define f (lambda (d) (set! d (- d 2)) d))
(define c
(f 10))
c
c
Что касается c1
, у нас есть вложенные лямбды
(define f1 (lambda (d) (lambda (p) (set! d (- d p)) d)))
((f1 10) 2)
((f1 10) 2)
8
и 8
. (Это то, что вы ожидали). Но на самом деле, то, что происходит,
(define c1
(f1 10))
(c1 2)
(c1 2)
возвращает 8
и 6
d получает memoised ( здесь - это пример Фибоначчи, использующего ту же процедуру запоминания и set!
).
Более того, для set!
вы не можете иметь наивную замену. Оценочная модель ракетки объясняет, как «создается новое местоположение для каждой переменной в каждом приложении»:
Поскольку значение, связанное с аргументной переменной x, можно изменить,
значение не может быть заменено на x, когда процедура начинается
приложенное.
tl; dr оценка c1
дает лямбду, которая закрывается в ожидании замены (окружение). Который затем мутирует на set!
при каждом вызове.