[SICP] 練習問題 4.6

Mar 10, 2024 11:52 ·

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 式になる。