Exercise 4.3
在這個練習中,我需要一些對錶的操作,下面就是關於表的操作:
(define (make-table)
(let ((local-table (list '*table*)))
(define (assoc key records)
(cond ((null? records) nil)
((equal? key (caar records)) (car records))
(else (assoc key (cdr records)))))
(define (lookup key)
(assoc key (cdr local-table)))
(define (insert! key value)
(let ((record (assoc key (cdr local-table))))
(if (not (null? record))
(set-cdr! record value)
(set-cdr! local-table
(cons (cons key value)
(cdr local-table))))))
(define (dispatch m)
(cond ((eq? m 'lookup) lookup)
((eq? m 'insert!) insert!)
(else (error "Unknown operation -- TABLE" m))))
dispatch))
(define (table-get table symbol)
((table 'lookup) symbol))
(define (table-put! table symbol value)
((table 'insert!) symbol value))
(define (binding-value binding)
(cdr binding))
與練習2.73一樣,有一些特殊情況不能應用數據導向的分派(sefl-evaluating ,variable,application),因爲這些表達式的car部分沒有顯式的表示它們的類型,所以需要單獨處理。對於其他情況,我們可以用分派方式簡單處理:
(define (eval exp env)
(cond ((self-evaluating? exp) exp)
((variable? exp) (lookup-variable-value exp env))
((get (car exp))
((get (car exp)) exp env))
((application? exp)
(apply (eval (operator exp) env)
(list-of-values (operands exp) env)))
(else
(error "Unkown expressioin type -- EVAL" exp))))
正如代碼所示,用分派方式處理的情況中,這些操作都需要兩個參數(exp和env),然後,我們之前的eval並不滿足這個條件所以,我們需要自己添加一些包裝函數:
(define (eval-quote exp env)
(text-of-quotation exp))
(define (eval-lambda exp env)
(make-procedure (lambda-parameters exp)
(lambda-body exp)
env))
(define (eval-begin exp env)
(eval-sequence (begin-actions exp) env))
(define (eval-cond exp env)
(eval (cond-if exp) env))
接下來,就是定義表,以及把過程添加到表中:
(define eval-table (make-table))
(define (get type)
(let ((binding (table-get eval-table type)))
(if (null? binding)
#f
(binding-value binding))))
(define (put type item) (table-put! eval-table type item))
(put 'quote eval-quote)
(put 'set! eval-assignment)
(put 'define eval-definition)
(put 'if eval-if)
(put 'lambda eval-lambda)
(put 'begin eval-begin)
(put 'cond eval-cond)