SICP 読み (145) 4.1.2 式の表現
ちょっと現実トウヒのつもりがハマりそうな予感。(を
問題 4.6
これ、結構厄介なのかなぁ。
gosh> (define sample '(let* ((x 3) (y (+ x 2)) (z (+ x y 5))) (* x z))) sample gosh> sample (let* ((x 3) (y (+ x 2)) (z (+ x y 5))) (* x z)) gosh> (cadr sample) ((x 3) (y (+ x 2)) (z (+ x y 5))) gosh> (list (car (cadr sample))) ((x 3)) gosh> (list 'let (list (car (cadr sample)))) (let ((x 3))) gosh>
うーん。無理矢理でっち上がったのが以下。
(define (let*->nested-let exp) (define (let*->nested-let-iter arg) (cond ((null? arg) '()) (else (list 'let (list (car arg)) (let*->nested-let-iter (cdr arg)))))) (append (let*->nested-let-iter (cadr exp)) (cddr exp)))
gosh に吸わせてみた。
gosh> (define (let*->nested-let exp) (define (let*->nested-let-iter arg) (cond ((null? arg) '()) (else (list 'let (list (car arg)) (let*->nested-let-iter (cdr arg)))))) (append (let*->nested-let-iter (cadr exp)) (cddr exp))) let*->nested-let gosh> (let*->nested-let sample) (let ((x 3)) (let ((y (+ x 2))) (let ((z (+ x y 5))) ())) (* x z)) gosh>
NG。てーか適当感満載だなぁ。あ、null? だったら (cddr exp) を戻せば良さげ。
gosh> (define (let*->nested-let exp) (define (let*->nested-let-iter arg) (cond ((null? arg) (cddr exp)) (else (list 'let (list (car arg)) (let*->nested-let-iter (cdr arg)))))) (let*->nested-let-iter (cadr exp))) let*->nested-let gosh> (let*->nested-let sample) (let ((x 3)) (let ((y (+ x 2))) (let ((z (+ x y 5))) ((* x z))))) gosh>
このケイスでは caddr で良いのか。
gosh> (define (let*->nested-let exp) (define (let*->nested-let-iter arg) (cond ((null? arg) (caddr exp)) (else (list 'let (list (car arg)) (let*->nested-let-iter (cdr arg)))))) (let*->nested-let-iter (cadr exp))) let*->nested-let gosh> (let*->nested-let sample) (let ((x 3)) (let ((y (+ x 2))) (let ((z (+ x y 5))) (* x z)))) gosh> (let ((x 3)) (let ((y (+ x 2))) (let ((z (+ x y 5))) (* x z)))) 39 gosh>
でもなんか微妙。もう少し賢そうなやり方は無いものか。
'() '(let ((x 3))) '(let ((x 3)) (let ((y (+ x 2))))) '(let ((x 3)) (let ((y (+ x 2))) (let ((z (+ x y 5)))))) '(let ((x 3)) (let ((y (+ x 2))) (let ((z (+ x y 5))) (* x z))))
上記のようなデキ上がりになれば良いんでしょうが、不可能な気がするなぁ。いや、cdr が null な car (いっちゃんケツのリスト) に対して append すればデキそう。最後の手続きも同様か。あ、違うな。先頭が let な一番ケツのリストに append か。
なんかデキない事はない気がしますが面倒スギ。試験を考えよう。
試験の検討
なんとか繰り返しにできんかなソレの検討中に、let が入れ子になってたら (手続き部分の中で) どうなるんだろう、と思ってしまった。多分なんとかなるんだろうな。(を
("let*->nested-let" ("first" (let ((l '(let* ((x 3) (y (+ x 2)) (z (+ x y 5))) (* x z))) (result '(let ((x 3)) (let ((y (+ x 2))) (let ((z (+ x y 5))) (* x z))))) (result2 '((lambda (x) ((lambda (y) ((lambda (z) (* x z)) (+ x y 5))) (+ x 2))) 3))) (assert-equal result (let*->nested-let l)) (assert-equal result2 (let->combination (let*->nested-let l))) ) ) )
で、上記のような試験をでっち上げてみたら NG との事。
-- (test case) let*->nested-let: F expected:<((lambda (x) ((lambda (y) ((lambda (z) (* x z)) (+ x y 5))) (+ x 2))) 3)> but was:<((lambda (x) (let ((y (+ x 2))) (let ((z (+ x y 5))) (* x z)))) 3)> in first
ははー。言われてみると確かに見てるのは一発目だけだよな。これ、どうなるんだろ。ちなみに直前エントリで
(eval (let->combination (let*->nested-let exp)) env)
ではないか、と書いてますがこれはこれでビンゴなんだろうか。