SICP 4.1.2 Representing Expressins
Exercise 4.2
a.スペシャルフォームかどうかを先に評価しないと駄目。SICPの最初の方でifはなんでスペシャルフォームなのかと同じ理由。(define x 3)の場合、defineがapplicationだと見なされ、引数を先に評価しようとして、xがlookupできずエラーになる。
b.とりあえず動いた。evalはeval-oに、apllyもapply-oに変更してあります。-oは俺様のo。エラーメッセージも、写経だと処理系のエラーメッセージと区別がつきにくいので、最後にnyoの署名を入れてあります。nyoはニョガーンのnyo。
教科書のevalはこう変更。
(define (eval-o exp env)
(cond ((self-evaluating? exp) exp)
((variable? exp) (lookup-variable-value exp env))
((quoted? exp) (text-of-quotation exp))
((call? exp) (apply-o (eval-o (call-operator exp) env) ;追加
(list-of-values (call-operand exp) env)))
((assignment? exp) (eval-assignment exp env))
((definition? exp) (eval-definition exp env))
((if? exp) (eval-if exp env))
((lambda? exp)
(make-procedure (lambda-parameters exp)
(lambda-body exp)
env))
((begin? exp)
(eval-sequence (begin-actions exp) env))
((cond? exp) (eval (cond->if exp) env))
((application? exp)
(apply-o (eval-o (operator exp) env)
(list-of-values (operands exp) env)))
(else
(error "Unknown expression type nyo -- EVAL" exp))))
callが呼ばれたら、一個ずらしてそのままapply-oへ。エラーチェック無し。
((call? exp) (apply-o (eval-o (call-operator exp) env) ;追加
(list-of-values (call-operand exp) env)))
call周りで作った手続きはこれ。
(define (call? exp) (tagged-list? exp 'call))
(define (remove-call exp) (cdr exp))
(define (call-operator exp)
(operator (remove-call exp)))
(define (call-operand exp)
(operands (remove-call exp)))
driver-loopが使いにくいので、直接俺様evalを呼び出してテスト
(define the-grobal-environment (setup-environment))
(eval-o '(define echo (lambda (x) x)) the-grobal-environment)
(trace application?)
(trace apply-o)
(trace call?)
普通の呼び出しだとこう。
(eval-o '(echo 'abc) the-grobal-environment)
gosh> CALL call? (echo (quote abc))
RETN call? #f
CALL application? (echo (quote abc))
RETN application? #t
CALL apply-o (pr...re (...) (...) ((...))) (abc)
RETN apply-o abc
abc
call?が#fを返し、application?が#tなので、apply-oに展開されたechoが渡される。
次にcallを使った呼び出しはこう。
(eval-o '(call echo 'abc) the-grobal-environment)
gosh> CALL call? (call echo (quote abc))
RETN call? #t
CALL apply-o (pr...re (...) (...) ((...))) (abc)
RETN apply-o abc
abc
call?が#tを返すので、追加した部分が評価され、apply-oに上のapplication?が#tを返したときと同じパラメータを渡している。
((call? exp) (apply-o (eval-o (call-operator exp) env) ;追加
(list-of-values (call-operand exp) env)))
結果は同じ。
問題は解けたけど、効率的になったかどうかは不明。
ここまでは動くファイルはここ。
The comments to this entry are closed.


Comments