새 문법을 평가기가 이미 아는 규칙으로 다시 쓴다.
let을 lambda 적용으로 바꾸면 바인딩 의미를 유지하면서 평가기 핵심을 작게 둘 수 있습니다.
let을 lambda 적용으로 바꿀 때 무엇이 그대로 남아야 할까요?
- Separate surface syntax from evaluator core forms
- Collect binding names as lambda parameters
- Collect binding expressions as application operands
- Evaluate the transformed expression in the original environment
The transformer takes the binding names from let and places them in a lambda parameter list. It puts the let body in that lambda and places the binding expressions after the lambda as application operands.
The evaluator does not need a second implementation of local binding. Its let case rewrites the expression and sends the result back through the ordinary lambda and application cases in the same environment.
(begin
(define (binding-name binding) (car binding))
(define (binding-value binding) (cadr binding))
(define (let->combination expression)
(let ((bindings (cadr expression))
(body (caddr expression)))
(cons (list 'lambda (map binding-name bindings) body)
(map binding-value bindings))))
(let->combination '(let ((x 10) (y 32)) (+ x y))))- 출력
- —
- 값
- —
- 진단
- —
The first program returns ((lambda (x y) (+ x y)) 10 32). The second returns 42.
In the second run, find the let dispatch and the transformer calls before the lambda is created. The later application extends the environment with x and y, then evaluates the original body.
힌트를 보기 전에 프로그램을 바꿔 보세요.
Add a z binding with value 8 and change the body to (+ (+ x y) z). Predict both the transformed expression and its value.
힌트 하나 보기
The parameter and operand lists grow in the same order. The body remains one expression inside the lambda.