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」カテゴリの記事
- 逆襲のSICP5.51 その後2(2009.05.16)
- 逆襲のSICP5.51 その後1(2009.04.04)
- 逆襲のSICP5.51(2009.02.04)
- またしてもやられた件について(onLisp)(2008.12.21)
- 久しぶりにハマった件について(2008.11.15)


コメント