« SICP問題5.49 | トップページ | SICP私的解答パック »

SICP問題5.50

超循環評価器を翻訳して、レジスタ計算機で動かすという問題。
scheme→(翻訳)→レジスタ計算機のコード→(実行)
ここまでくるともうなにがなにやらみたいな状態になってきます。

とりあえず問題文にあるとおり、beginでくくって問題5.49に食わせればいいかな、と思っていたんですが、そうは問屋がおろさないというやつで、そのまんまだと動きませんでした。
と、いうわけで以下無理やり動かすための修正点です。

1.基本手続きが足りない
レジスタ計算機の基本手続きはつまるところ超循環評価器の基本手続きなので、ここに超循環評価器がつかう手続きを入れておく必要があります。
というわけで超循環評価器に手続きを片っ端から追加しました。

(define primitive-procedures
  (list (list 'car car)
        (list 'cdr cdr)
        (list 'cons cons)
        (list 'null? null?)
        (list 'square (lambda (x) (* x x)))
        (list '= =)
        (list '< <)
        (list '<= <=)
        (list '> >)
        (list '>= >=)
        (list '+ +)
        (list '- -)
        (list '* *)
        (list '/ /)
        (list 'apply apply)
        (list 'map map)
        (list 'let let)
        (list 'pair? pair?)
        (list 'eq? eq?)
        (list 'length length)
        (list 'set-car! set-car!)
        (list 'set-cdr! set-cdr!)
        (list 'display display)
        (list 'newline newline)
        (list 'read read)
        (list 'number? number?)
        (list 'string? string?)
        (list 'symbol? symbol?)
        (list 'caddr caddr)
        (list 'cdadr cdadr)
        (list 'cddr cddr)
        (list 'cadr cadr)
        (list 'cdddr cdddr)
        (list 'cadddr cadddr)
        (list 'caadr caadr)
        (list 'not not)
        (list 'append append)
        (list 'list list)))

2.mapが動かない(私だけ?)
超循環評価器でmapを使ってる部分が動きません。
どうもmapの引数として渡す手続きが(carとか)がうまく扱えてない模様。
評価器なおすのも面倒なので、とりあえずmapつかってるprimitive-procedure-namesとprimitive-procedure-objectsは以下のようにしちゃいました。

(define (primitive-procedure-names)
  '(car cdr cons null? square = < <= > >= + - * /))
(define (primitive-procedure-objects)
  (list car cdr cons null? (lambda (x) (* x x)) = < <= > >= + - * /))

まあほかにも(const ())が(const '())になってたのを直したとかありましたが、これは私のポカミスなのであんまり関係ないと思われます。

これで一応実行はできるはずです。というか私はできました。
factorialとかやらせてみるとやっぱり遅いですね。
trace-onとかすると、実行の過程がみれて楽しいです。

追記
エントリ書いた直後、ほかの人の解答をみてみたところ、mapの解決法が載ってました。
ありがたいことです。
要は超循環評価器の中にmapの定義を入れておけばよいとのこと。
というわけで、

(define (map proc list)
  (if (null? list)
    '()
    (cons (proc (car list))
          (map proc (cdr list)))))

ただ、これだけだとprimitiveが超循環評価器の基本手続きを基本手続きにしてる形になって、要は(primitive (primitive hoge))のような形になってしまうので、primitive-procedure-objectsも修正が必要。

(define (primitive-procedure-objects)
  (map (lambda (proc) (list 'primitive (cadadr proc)))
       primitive-procedures))

これをふまえた基本手続き一覧

(define primitive-procedures
  (list (list 'car car)
        (list 'cdr cdr)
        (list 'cons cons)
        (list 'null? null?)
        (list 'square (lambda (x) (* x x)))
        (list '= =)
        (list '< <)
        (list '<= <=)
        (list '> >)
        (list '>= >=)
        (list '+ +)
        (list '- -)
        (list '* *)
        (list '/ /)
        (list 'apply apply)
;        (list 'map map)
        (list 'let let)
        (list 'pair? pair?)
        (list 'eq? eq?)
        (list 'length length)
        (list 'set-car! set-car!)
        (list 'set-cdr! set-cdr!)
        (list 'display display)
        (list 'newline newline)
        (list 'read read)
        (list 'number? number?)
        (list 'string? string?)
        (list 'symbol? symbol?)
        (list 'caddr caddr)
        (list 'cdadr cdadr)
        (list 'cddr cddr)
        (list 'cadr cadr)
        (list 'cdddr cdddr)
        (list 'cadddr cadddr)
        (list 'caadr caadr)
        (list 'cadadr cadadr)
        (list 'not not)
        (list 'append append)
        (list 'list list)))

これのおかげで無事letも動くようになりました。
let*とか自分で作ったものはスコーンとgosh巻き添えにして落ちますが。
まあとりあえず満足です。

|

« SICP問題5.49 | トップページ | SICP私的解答パック »

SICP」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/213481/41923329

この記事へのトラックバック一覧です: SICP問題5.50:

« SICP問題5.49 | トップページ | SICP私的解答パック »