SICP 読み (343) 5.5 翻訳系
昨晩のソレを元に検討着手。とりあえず以前のエントリをカンニングだ。
- SICP 読み (147) 4.1.2 式の表現に let->combination の手続きがある
- SICP 読み (168) 4.1.6 内部定義で scan-out-defines な検討をしている
どーでも良い話なんですが、5 章に突入してから 100 エントリ位消費してるんでしょうか。自分でヤッててナニですが滅茶苦茶だな。
問題 5.43
ええと何ヤレば良いんだっけ。(こら
これが
(define (factorial n) (define (iter product counter) (if (> counter n) product (iter (* counter product) (+ counter 1)))) (iter 1 1))
こうなって
(define factorial (lambda (n) (define (iter product counter) (if (> counter n) product (iter (* counter product) (+ counter 1)))) (iter 1 1)))
scan-out-defines でこうなってくれ
(define factorial (lambda (n) (let ((iter '*unassigned*)) (set! iter (lambda (product counter) (if (> counter n) product (iter (* counter product) (+ counter 1))))) (iter 1 1))))
で let->combination でこうなってくれたものを
(define factorial (lambda (n) ((lambda (iter) (set! iter (lambda (product counter) (if (> counter n) product (iter (* counter product) (+ counter 1))))) (iter 1 1)) '*unassigned*)))
compile で翻訳できれば万歳。ってそんなに簡単に行くのかどうか。
つづき
って正確には一番てっぺんの式が compile に吸われた後は definition-value が lambda な式に直して compile に吸われる。これは compile-lambda が取り扱い責任者なんですが、この間で何とかしないと駄目だな。compile-lambda-body に渡る時点でもまだセイフかな。compile-sequence に渡る直前までに何とかしておく必要ありか。
あるいは
(compile-sequence (lambda-body exp) 'val 'return)
なソコで ... ってワケ分からんから gosh で試す。
gosh> (add-load-path ".") gosh> (load "ch5-syntax") gosh> (define scan-out-defines 略) gosh> (scan-out-defines '((+ a b))) ((+ a b)) gosh> (scan-out-defines '((define (iter product counter) (if (> counter n) product (iter (* counter product) (+ counter 1)))) (iter 1 1))) ((let ((iter '*unassigned*)) (set! iter (lambda (product counter) (if (> counter n) product (iter (* counter product) (+ counter 1))))) (iter 1 1))) gosh>
む。イケてる感じ。もう少し。ってここでいきなり let->combination に吸わせてハマる。compile に let->combination が仕込んであればいいんだからこうか
(compile-sequence (compile (scan-out-defines (lambda-body exp)) 'val 'next) 'val 'return)
中の compile な引数が微妙。しかも現時点で *unassigned* なソレを完全にスルーしてるしー。
とりあえず使用予定な手続き定義もメモ。
(define (scan-out-defines exp) (define (make-set exp) (let f ((init '()) (set '()) (exp exp)) (cond ((null? exp) (if (null? init) '() (append (list 'let init) set))) (else (cond ((definition? (car exp)) (f (append init (list (list (definition-variable (car exp)) ''*unassigned*))) (append set (list (list 'set! (definition-variable (car exp)) (definition-value (car exp))))) (cdr exp))) (else (f init set (cdr exp)))))))) (let ((result (make-set exp))) (cond ((null? result) exp) (else (list (append result (let f ((l '()) (exp exp)) (cond ((null? exp) l) ((definition? (car exp)) (f l (cdr exp))) (else (f (append l (list (car exp))) (cdr exp))))))))))) (define (let->combination exp) (append (list (make-lambda (map car (cadr exp)) (cddr exp))) (map cadr (cadr exp))))
しかし上記の scan-out-defines は今見るとミニクい。名前 let な内部手続きをうれしがって使ってた頃だなぁ。ちょっと手を入れてみるか。
(define (scan-out-defines exp) (define (make-set init set exp) (if (null? exp) (if (null? init) '() (append (list 'let init) set)) (if (definition? (car exp)) (make-set (append init (list (list (definition-variable (car exp)) ''*unassigned*))) (append set (list (list 'set! (definition-variable (car exp)) (definition-value (car exp))))) (cdr exp)) (make-set init set (cdr exp))))) (define (remove-define l exp) (cond ((null? exp) l) ((definition? (car exp)) (remove-define l (cdr exp))) (else (remove-define (append l (list (car exp))) (cdr exp))))) (let ((result (make-set '() '() exp))) (if (null? result) exp (list (append result (remove-define '() exp))))))
試験は別途とゆーコトでとりあえず投入。
エントリ投入時に気づいた
let でないかもしれんのに
(compile-sequence (compile (scan-out-defines (lambda-body exp)) 'val 'next) 'val 'return)
なコトしちゃ駄目ぢゃん。てか compile-sequence の中で個別に compile してるから let->combination は compile に組み込まれてれば
(compile-sequence (scan-out-defines (lambda-body exp)) 'val 'return)
で良さげ。
追記
手を入れた微妙な scan-out-defines ですが、誤りがあったので修正しとります。まだ微妙なカンジ。