« SICP 4.1.2 Representing Expressins その3 condとlet | Main | SICP 4.1.3 Evaluator Data Structure »

2007.09.09

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にとってローカル変数は関数呼出しのシンタックスシュガーにすぎないからです。

納得。

ここまで動くソースはここ


|

« SICP 4.1.2 Representing Expressins その3 condとlet | Main | SICP 4.1.3 Evaluator Data Structure »

Comments

Post a comment



(Not displayed with comment.)




TrackBack

TrackBack URL for this entry:
http://app.cocolog-nifty.com/t/trackback/18154/16389840

Listed below are links to weblogs that reference SICP 4.1.2 Representing Expressins その4 Let*とnamed let:

« SICP 4.1.2 Representing Expressins その3 condとlet | Main | SICP 4.1.3 Evaluator Data Structure »