SICP 読み (143) 4.1.2 式の表現
現実トウヒベースですが、なんかさくっと出来た。
問題 4.6
let を lambda に変換する手続き。例えば
(let ((tmp (assoc 'b '((a 1) (b 2))))) (if tmp (cadr tmp) #f))
だと
((lambda (tmp) (if tmp (cadr tmp) #f)) (assoc 'b '((a 1) (b 2))))
に変換されれば良い、のかな??
一応 gosh 上では同じ値が戻ってきたのでビンゴと見よう。ええと make-lambda は以下。
(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))
こんな感じ?? (draft)
(define (let->combination exp) (list (make-lambda vars (caddr exp)) exps))
これは let なソレの変数と値のリストをこさえんと駄目だな。gosh で試してみる。
gosh> (define l '(let ((a 1) (b 2) (c 3)) (+ a b c))) l gosh> l (let ((a 1) (b 2) (c 3)) (+ a b c)) gosh> (cadr l) ((a 1) (b 2) (c 3)) gosh> (map car (cadr l)) (a b c) gosh> (map cadr (cadr l)) (1 2 3) gosh>
こんな感じ??
(define (let->combination exp) (list (make-lambda (map car (cadr exp)) (caddr exp)) (map cadr (cadr exp))))
なんか簡単にできすぎだなぁ。とりあえず別途試験を作ろう。
と言いつつ
gosh でさくっと試してみた。微妙。
gosh> (define (let->combination exp) (list (make-lambda (map car (cadr exp)) (caddr exp)) (map cadr (cadr exp)))) let->combination gosh> (let->combination l) *** ERROR: unbound variable: make-lambda Stack Trace: _______________________________________ 0 (make-lambda (map car (cadr exp)) (caddr exp)) At line 18 of "(stdin)" gosh> (define (make-lambda parameters body) (cons 'lambda (cons parameters body))) make-lambda gosh> (let->combination l) ((lambda (a b c) + a b c) (1 2 3)) gosh> l (let ((a 1) (b 2) (c 3)) (+ a b c)) gosh>
caddr じゃなくって cddr かも。
gosh> (define (let->combination exp) (list (make-lambda (map car (cadr exp)) (cddr exp)) (map cadr (cadr exp)))) let->combination gosh> (let->combination l) ((lambda (a b c) (+ a b c)) (1 2 3)) gosh> ((lambda (a b c) (+ a b c)) (1 2 3)) *** ERROR: Compile Error: wrong number of arguments: #f requires 3, but got 1 "(stdin)":29:((lambda (a b c) (+ a b c)) (1 2 3)) Stack Trace: _______________________________________ gosh> ((lambda (a b c) (+ a b c)) 1 2 3) 6 gosh>
むむ。しまった。ケツのソレはリストにしちゃマズいなぁ。(とほほ
で
でっち上がったのが以下。なんか微妙。
(define (let->combination exp) (let f ((l (list (make-lambda (map car (cadr exp)) (cddr exp)))) (exps (map cadr (cadr exp)))) (if (null? exps) l (f (append l (list (car exps))) (cdr exps)))))
なんかがちゃがちゃしてるなぁ。一応 gosh 上ではまともに動いてそげ。
gosh> (let->combination l) ((lambda (a b c) (+ a b c)) 1 2 3) gosh> ((lambda (a b c) (+ a b c)) 1 2 3) 6 gosh>
あら? append すれば良いのかな?
(define (let->combination exp) (append (list (make-lambda (map car (cadr exp)) (cddr exp))) (map cadr (cadr exp))))
を、動いた。試験は別途で。しかも全然ダメだったりして (を
試験
なんだか調子悪いなぁ。以下のようなのしか出てこない。
("let->combination" ("first" (let ((l '(let ((a 1) (b 2)) (+ a b))) (result '((lambda (a b) (+ a b)) 1 2))) (assert-equal result (let->combination l)) ) ) ("second" (let ((l '(let ((a 1) (b 2) (c 3)) (+ a b) (+ b c))) (result '((lambda (a b c) (+ a b) (+ b c)) 1 2 3))) (assert-equal result (let->combination l)) ) ) )
しかも非常に微妙なボケを発見。蚊もいる。なんかかゆいし。
eval への盛り込み
以下を追加。たぶん正しいと思う。試験ができないんで心配。
((let? exp) (eval (let->combination exp) env))
ちなみに上記の微妙なボケは let? の試験をしている時に発覚。仕方が無いので以下にログを。
ボケ
以下のような試験を書いてて、全部の分岐をパスしている、と思っていました。
("verification of type of exp" ("lot" (define (tagged-list? exp tag) (if (pair? exp) (eq? (car exp) tag) #f)) (assert-true (assignment? '(set! a b))) (assert-true (not (assignment? '(a b c)))) (assert-true (definition? '(define a b))) (assert-true (not (definition? '(a b c)))) (assert-true (lambda? '(lambda a b))) (assert-true (not (lambda? '(a b c)))) (assert-true (if? '(if a b))) (assert-true (not (if? '(a b c)))) (assert-true (begin? '(begin a b))) (assert-true (not (begin? '(a b c)))) (assert-true (application? '(a . b))) (assert-true (application? '(a b c))) (assert-true (not (application? '()))) (assert-true (not (application? '#(a b)))) (assert-true (let? '(let ((a 1) (b 2)) (+ a b)))) (assert-true (not (let? '(a 1)))) ) )
で、最初は let? の試験で以下を入れてたんですが通らない。
(assert-true (not (let? '())))
不具合なメセジを見るに false が解決できん、と出ている。ローカル側で定義されている tagged-list? が使われてる、って思っていたんですが違う事が判明。
てー事は pair? ではない試験ができていない、という事なんですか。とほほ。