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? ではない試験ができていない、という事なんですか。とほほ。