問題4-2〜3

「4.1.2 式の表現」ということで、evalに渡された式が何者で、それをどう評価するべきなのかということが述べられています。渡された式が変数なのか、何かを定義するのか、純粋に作用させる式なのか。それらをcond式で判別して、式の形式がわかったら然るべき処理を行なうというのがevalです。
問題4-2。Louisの仮説が間違っていることを説明せよと問われています。渡された式が手続き作用かどうかを判別する(application? exp)は、evalの中のcondの最後に配置されています。その前に様々な型チェックを行なうのは効率が悪いと主張しています。しかし、例えば(application? exp)を(definition? exp)よりも前に配置して、(define x 3)をevalに渡してしまうと、(tagged-list? exp 'define)に引っかかって、(eval-definition exp env)を行なう処理を通る前に、(define x 3)がapplyされてしまいます。そうなると、defineという手続きに、xと3が作用されてしまい、本来の式を定義するという処理が行なわれなくなってしまいます。
Louisの主張を受け入れる為には、手続き作用だとわかっている式の前にcallと書いてやって、(application? exp)の定義を、

(define (application? exp) (tagged-list? exp 'call))

として、operatorやoperandsを取得する手続きを、

(define (operator exp) (cadr exp))
(define (operands exp) (cddr exp))

と変更してやる必要がありそうです。その他、ただの対では(application? exp)に反応しなくなってしまったので、幾度かの評価の結果、手続き作用の要素が抽出されたら、それにcallを付け加えてやる必要もあるのではないかと思われます。
問題4-3。eval内のcondロジックを、データ主導流に振り分けるような形式に書き替えます。tagged-list?を使って型の判断をしているものが、移行対象となります。(self-evaluating? exp)と(variable? exp)、及び(application? exp)は、そのままevalの中に配置します。時間がかかりそうだし、正しいかどうかの検証も現段階ではできないので、コードを書くのは後回しにしますが、(self-evaluating? exp)と(variable? exp)はそのままにしておいて、その後、(get (car exp))のような式を書いて、あらかじめputを使って登録してあるタグの内容を取得しようと試みます。何らかのデータがあれば、その処理を行ない、なければ、その式は手続き作用ということなので、applyを実行します。