let 式は派生式である。以下は、 (let ((⟨var1⟩ ⟨exp1⟩) . . . (⟨varn⟩ ⟨expn⟩)) ⟨body⟩) 次のものと等価だからだ。 ((lambda (⟨var1⟩ . . . ⟨varn⟩) ⟨body⟩) ⟨exp1 ⟩ … ⟨expn⟩) let 式の評価を、上記のような組み合わせの評価に帰着させる構文 変形 let->combination を実装せよ。また、eval に適切な節を追 加し、let 式を扱えるようにせよ。
解答 🔗
let 式を判別できるようにするため、let?
を実装する。
(define (let? exp) (tagged-list? exp 'let))
eval
が let 式を受け取ったら、let 式を lambda 式に変換するlet->combination
を呼ぶようにする。
(define (eval exp env)
(cond ((self-evaluating? exp) exp)
...
((let? exp) (eval (let->combination exp) env))
...
最後に let 式を lambda 式に変換する let->combination
を実装する。
(define (let->combination exp)
(let (
(variables (map car (cadr exp)))
(values (map cadr (cadr exp)))
(body (cddr exp)))
(cons (make-lambda variables body) values)))
(list (make-lambda variables body) values)
にすると ('lambda '(変数1,変数2,...) '(値1 値2))
となり、正しい Lambda 式にならないので注意する。
(cons (make-lambda variables body) values)
だと、('lambda '(変数1,変数2,...) 値1 値2)
となり、正しい Lambda 式になる。