SICP 読み (147) 4.1.2 式の表現

業者連絡待ちの間に (以下略
しかし保守契約を結ばないとファームのアプデイトもできんとは、一体どーゆー事なんでしょうかねぇ。セキュリティパッチとは異なるソレなんでしょうか。

問題 4.8

名前付き let を導出、との事。以下の手続きはどう変換されるべきなのか。

(define (fib n)
  (let fib-iter ((a 1)
		 (b 0)
		 (count n))
    (if (= count 0)
	b
	(fib-iter (+ a b) a (- count 1)))))

4.6 では let が lambda に変換された、という事で同じ形にするのかな。どうなるべき、なんだろうか。

(define (fib n)
  (define fib-iter
    (lambda (a b count)
      (if (= count 0)
	  b
	  (fib-iter (+ a b) a (- count 1)))))
  (fib-iter 1 0 n))

手続きな部分はそのまんまなので、やってデキない訳ではなさげ。

gosh> (define l '(let fib-iter ((a 1)
		 (b 0)
		 (count n))
    (if (= count 0)
	b
	(fib-iter (+ a b) a (- count 1))))
)
l
gosh> (cadr l)
fib-iter
gosh> (caddr l)
((a 1) (b 0) (count n))
gosh> (cadddr l)
(if (= count 0) b (fib-iter (+ a b) a (- count 1)))
gosh> (list 'lambda (map car (caddr l)) (cdddr l))
(lambda (a b count) ((if (= count 0) b (fib-iter (+ a b) a (- count 1)))))
gosh> 

lambda 式を作る手順は同じですが、取り出す位置が違うな。とりあえず手続きをベタに書いてみよう。元は以下。

(define (let->combination exp)
  (append (list (make-lambda (map car (cadr exp)) (cddr exp)))
	  (map cadr (cadr exp))))

えーと、どうやって切り分ければ良いのかな。cadr が symbol? って聞けば良いと見よう。

(define (let->combination exp)
  (if (symbol? (cadr exp))
      (list 'define 
	    (cadr exp)
	    (list 'lambda (map car (caddr exp)) (cdddr exp))
	    (list (cadr exp) (map cadr (caddr exp))))
      (append (list (make-lambda (map car (cadr exp)) (cddr exp)))
	      (map cadr (cadr exp)))))

うわ、微妙。then ブロックなソレは動作確認してません。やってみよ。

gosh> (list 'define
(cadr l)
(list 'lambda (map car (caddr l)) (cdddr l))
(list (cadr l) (map cadr (caddr l))))
(define fib-iter (lambda (a b count) ((if (= count 0) b (fib-iter (+ a b) a (- count 1))))) (fib-iter (1 0 n)))
gosh> 

最早、合ってるのかどうかさえ不明 (何
えーと、何が何だかワケワカらんぞ。if の前に括弧が二つあるな。これは make-lambda を使ってないからかな??あ、その前の list も不要。
もう一つ。define なリストが終わってから手続き呼び出しだな。あら??なんじゃそれは。二つもリストは戻せないと思うんだけど。最初に戻らないと駄目ぽ。まぢ??

つづき

元に戻りかけたんですが、begin を使う、という解を見いだす。微妙??

(define (let->combination exp)
  (if (symbol? (cadr exp))
      (list 'begin
	    (list 'define 
		  (cadr exp)
		  (make-lambda (map car (caddr exp)) (cdddr exp)))
	    (list (cadr exp) (map cadr (caddr exp))))
      (append (list (make-lambda (map car (cadr exp)) (cddr exp)))
	      (map cadr (cadr exp)))))

この then ブロックなソレを gosh に吸わせてみる。

gosh> (list 'begin
	    (list 'define 
		  (cadr l)
		  (make-lambda (map car (caddr l)) (cdddr l)))
	    (list (cadr l) (map cadr (caddr l))))
(begin (define fib-iter (lambda (a b count) (if (= count 0) b (fib-iter (+ a b) a (- count 1))))) (fib-iter (1 0 n)))
gosh> l
(let fib-iter ((a 1) (b 0) (count n)) (if (= count 0) b (fib-iter (+ a b) a (- count 1))))
gosh> 

出力はどうか。

(begin 
  (define fib-iter 
    (lambda (a b count) 
      (if (= count 0) b (fib-iter (+ a b) a (- count 1))))) 
  (fib-iter (1 0 n)))

ええ感じ、なのかなぁ。まずはこれで試験を作ってみよう。