Понимание подстановки лямбда в Redex
Допустим, в Redex у меня есть следующее определение:
(define-language L
[e ::= (λ x e) (e e) x]
[x ::= variable-not-otherwise-mentioned]
#:binding-forms
(λ x e #:refers-to x))
Я бы подумал, что выражение (λ y x) x
средства:
заменить появление y
в x
(внутри фигурных скобок в приведенном выше выражении) на x
(вне скобок). А поскольку нетy
в x
, ответ должен быть просто x
. потом(λ y x) x y
должен вернуться x y
. Но:
(default-language L)
(term (substitute (λ y x) x y))
'(λ y«0» y)
почему он возвращает функцию? А что значитy<<0>>
жадный? Я не понимаюterm (substitute ..)
?
Я тоже не понял этого результата:
(term (substitute (λ y x) x true))
'(λ y«1» true)
Может ли кто-нибудь помочь мне это расшифровать? Я новичок в Racket/Redex.
1 ответ
y«0»
а также y«1»
просто означает, что пока переменная называется y
это другое y
чем тот, который прошел. #:refers-to
Флаг используется для того, чтобы формы учитывали замену, исключающую захват.
В общем, идея такая, каким должен быть результат этой программы:
((lambda (x) (lambda (y) x))
y)
Если эта программа оценивается как 4
или 3
? Если использовать простую подстановку, то можно сказать, что программа сводится к:
(lambda (y) y)
Это функция идентичности. Это заметно, если мы, скажем, ограничим y равным 5 и назовем результат:
(let* ([y 5]
[f ((lambda (x) (lambda (y) x))
y)])
(f 6))
Здесь мы ожидаем, что результат будет 5
, хотя мы проезжаем 6
в f
. Это потому, чтоy
в результате указывает на первый y
в let*
. Вы можете увидеть это, если вы укажетеy
в DrRacket.
Чтобы избежать этого, вместо простой замены всех x
s в выражении to y
s, он переименовывает все идущие вниз подшивки на новые имена, поэтому вместо этого вы получаете:
(lambda (y«0») y)
И теперь ясно, что двое y
s в этом выражении разные.