問題4-16
「4.1.6 内部定義」に入りました。四章の第一節もゴールが見えてきましたが、このトピックは問題が多く、しかも一筋縄では解けそうにないので、ちょっと参っています。
問題4-16を解く前に、問題4-6で定義した自前のletが正しく動くかを試してみました。結果はダメでした。ここブログの解答例で試してみたら動きました。以下がそれですが、どうやら自分の定義は、大筋では正しかったものの、細かいリスト内の要素の取得ロジックに問題があったようです。
(define (let? exp) (tagged-list? exp 'let)) (define (let-variables exp) (map car (cadr exp))) (define (let-expressions exp) (map cadr (cadr exp))) (define (let-body exp) (cddr exp)) (define (let->combination exp) (cons (make-lambda (let-variables exp) (let-body exp)) (let-expressions exp)))
問題4-16の内部定義を変換するscan-out-defineについてですが、手続き本体にdefineがあったら、let式に変換していき、'*unassaigned*で束縛したり、set!で変更したりする手続きを組み込んでやればよさそうです。ただ、上手く書けなそうだったので、ここのエントリーで描かれていたコードを参考にしました。非常に上手く書かれていて、すんなりと納得することができました。
問題4-17については、let式変換バージョンだと、letがevalされた時にlambda式に変換され、そのlambdaはmake-procedureによってcompond-procedureとなり、こうなるとapply時にextend-environmentによって新しいフレームが作成されるから、問題文に書いてあるような状態になるのではと思いましたが、これ以上思考が進まなかったため、深追いするのはやめました。