SICP 4.1.2 Representing Expressins その4 Let*とnamed let
効率を上げるために、開発環境をcygwinのEmacsからMeadowに変更。これで、日本語打ちながら動作確認できる。
Exercise 4.7 Let*の問題
まずは四則演算を処理系に追加しないと、動作確認できない。
(define primitive-procedures
(list (list 'car car)
(list 'cdr cdr)
(list 'cons cons)
(list 'null? null?)
(list '+ +) ;追加
(list '- -) ;追加
(list '* *) ;追加
(list '/ /) ;追加
(list '= =) ;追加
))
(let*->nested-lets '(let* ((x 3) (y (+ x 2)) (z (+ x y 5))) (* x z)))の結果がこうなるはず。
(let ((x 3))
(let ((y (+ x 2)))
(let ((z (+ x y 5)))
(* x z))))
たた単に、letをネストさせれば終わりなんだが、letのネスト作るの難しい。♪consをしても、listをしても、つくれーないよ。letのネスト 思った以上に強敵
いろいろやってできた。
(define (let*? exp) (tagged-list? exp 'let*))
(define (let*-make-lets vlist body)
(if (null? vlist)
(car body)
(list 'let (cons (car vlist) '())(let*-make-lets (cdr vlist) body))))
(define (let*->nested-lets exp)
(let ((vlist (let-vlist exp)) (body (let-body exp)))
(let*-make-lets vlist body)))
だんだんきもくなってきたので、let-oをletに戻す。+の引数が3個で変数が入ったとき計算結果がおかしいがスルー。
(let* ((x 3) (y (+ x 2)) (z (+ x y 5))) (* x z))
(eval-o '(let* ((x 3) (y (+ x 2)) (z (+ x (+ y 5)))) (* x z)) the-grobal-environment)
gosh> 39
OK!
exercise 4.8 named letの問題
(define (fib n)
(let fib-iter ((a 1) (b 0) (count n))
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1)))))
をこれに変えれば良い。
(define (fib n)
(let ((a 1) (b 0) (count n))
(define (fib-iter a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
(fib-iter a b count)))
追加、変更はここ
(define (let->combination exp)
(if (named-let? exp)
;; named let
(let ((vlist (named-let-vlist exp))
(proc-name (named-let-procname exp))
(body (named-let-body exp)))
(list 'let
vlist
(named-let-make-lambda proc-name vlist body)
(named-let-make-call proc-name vlist)))
;;normal let
(let ((vlist (let-vlist exp)))
(let-make-combination
(make-lambda (let-make-arg vlist) (let-body exp))
(let-make-parameter vlist)))))
(define (named-let-make-call proc-name vlist)
(cons proc-name (map car vlist)))
(define (named-let-make-lambda proc-name vlist body)
(list 'define (cons proc-name (map car vlist)) body))
(define (named-let? exp)
(symbol? (car (cdr exp))))
(define (named-let-procname exp)
(car (cdr exp)))
(define (named-let-vlist exp)
(car (cdr (cdr exp))))
(define (named-let-body exp)
(car (cdr (cdr (cdr exp)))))
(eval-o '(define (fib n)
(let fib-iter ((a 1) (b 0) (count n))
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))) the-grobal-environment)
(eval-o '(fib 10) the-grobal-environment)
で55返って来た。ワショーイ
Exercise 4.9とExercise 4.10はパス。
ひげぽんさんの所から
関数型言語の勉強にSICPを読もう - (65) 4章 - 超言語的抽象(222ページ) C++でSchemeインタプリタを作ろう14も意味が分かるようになっている。
shiro >その答えは、Schemerにとってローカル変数は関数呼出しのシンタックスシュガーにすぎないからです。
納得。
ここまで動くソースはここ
The comments to this entry are closed.


Comments