value関数(その2)

ようやく読了したよ、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種類の関数を返してますな。
先に種明かしをしとくと、これらのアクションは

を引数として要求する。
ただし、第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の部分だけだけど)が完成するわけね!