Schemeの課題をあの実装で の3

今回moshの予定だったけど今のところうまく行ってない(暇なx86マシンを準備してない)ので別の実装で。

dryScheme

研究室で、ついに念願のPLAYSTATION3を手に入れたのでCell向けにいろいろする予定。その細かいテストの記述やコードの生成などの目的のためにSchemeインタプリタを作ることにした。
研究には時間的余裕が無いので、既存のschemeインタプリタ(minischeme)をC言語からschemeに移植している。Bootstrap lispの精神で、scheme部分とC部分を自由に調整できるようにデザインしたいというのが目的。

まぁ最大の理由はschemeの復習だけど*1。。
このschemeschemeで書かれているのでR5RSなほかのschemeで単に実行する。初期化ファイルとしてinit.scmが必要だが、これはminischemeに同梱されている。
このschemeはR5RSの要素の大部分を欠いているので、自分自身を処理できない*2。これはそのうち修正される予定。
今後は、巨大なcondで実現しているインタプリタ部分を個々のS式に分解して、マクロで元にもどす作業。要するに :

  • init.scmに含むもの
  • C/Schemeコードで実装するもの

を自由に分類したい話。たとえば + は2要素の足し算の繰り返しとして実装しているが、2要素の足し算だけをC側に組み込み、多要素の足し算はinit.scmに移すといったことが出来るのが好ましい。

make-list

(define make-list
  (lambda (x)
    (if (= 0 x) '() (cons x (make-list (- x 1))))))
make-list
=>(make-list 4)
(4 3 2 1)

リストは(cons 1 '())または(cons 2 (cons 1 '()))のように作れる。作りたいリストをconsで考えれば、とても再帰的なことに気づく。

(define make-list2
  (lambda (x)
    (define make-list-itr
      (lambda (p x l)
        (if (< x p)
            l
            (make-list-itr (+ p 1) x (cons p l)))))
    (make-list-itr 1 x '())))
make-list2
=>(make-list2 4)
(4 3 2 1)

末尾再帰版は「返したいものをパラメタにしておく」いつもの書き換えで作ることができる。開始時がnullリストなので進行方向を逆にするか、全部作った後でreverseして返す。

*1:自動生成できそうなもんだが、写経の要領で全部手で書き直している。深夜から10時間くらい掛けて。。

*2:自分自身を実行できると、scheme処理系にscheme処理系を重ねる遊びができる