ようやく読了したよ、The Little Schemer。
ということで、あと2、3回くらいでこの本に関する日記も終わりそう。
さて、まずS式を受け取って、そのS式のタイプ(id:yagiey:20081107の表を参照)に応じた動作をする関数(以下、アクション)を返すexpression-to-action関数を以下のように定義する。
(define expression-to-action (lambda (e) (cond ((atom? e) (atom-to-action e)) (else (list-to-action e)))))
さらに、補助関数であるatom-to-actionとlist-to-actionを以下のように定義する。
ちなみに、atom-to-actionとlist-to-actionは演習問題なので、自分でやってみると吉。
(define atom-to-action (lambda (e) (cond ((number? e) *const) ((eq? e #f) *const) ((eq? e #t) *const) ((eq? e 'cons) *const) ((eq? e 'car) *const) ((eq? e 'cdr) *const) ((eq? e 'null?) *const) ((eq? e 'eq?)) *const) ((eq? e 'atom?)) *const) ((eq? e 'zero?)) *const) ((eq? e 'add1)) *const) ((eq? e 'sub1)) *const) ((eq? e 'number?) *const) (else *identifier)))) (define list-to-action (lambda (e) (cond ((atom? (car e)) (cond ((eq? (car e) 'quote) *quote) ((eq? (car e) 'lambda) *lambda) ((eq? (car e) 'cond) *cond) (else *application))) (else *application))))
id:yagiey:20081107で出てきた6個のタイプに対応する6種類の関数を返してますな。
先に種明かしをしとくと、これらのアクションは
- S式
- テーブル(id:yagiey:20081105)
を引数として要求する。
ただし、第1引数として渡されたS式が妥当かどうかについては一切関知しない。
このexpression-to-action関数を利用すると、value関数は以下のように書けるね、と。
(define value (lambda (e) (meaning e '()))) (define meaning (lambda (e table) ((expression-to-action e) e table)))
補助関数としてmeaning関数なるものが出てきてる。
こいつは、第1引数で渡されたS式にふさわしいアクションを探して(expression-to-action適用している所ね)、そのアクションに第1引数とテーブル投げて値を決める関数。
meaning関数が正しいアクションを探してくれるから、各アクションに妥当なS式が渡っていることが保障されているわけですな。
んで、第2引数のテーブルは何に使われるのかなー?
それは次回以降のお楽しみ。
次回からは、6個のアクションを実装していく予定。
6個全部完成したとき、なんちゃってLISPの処理系(といっても、REPLのうち、Eの部分だけだけど)が完成するわけね!