Exercise 4.14. Eva Lu Ator and Louis Reasoner are each experimenting with the metacircular evaluator. Eva types in the definition of map, and runs some test programs that use it. They work fine. Louis, in contrast, has installed the system version of map as a primitive for the metacircular evaluator. When he tries it, things go terribly wrong. Explain why Louis’s map fails even though Eva’s works.
我们当然不能把 map 这样添加到 environment 中
(define primitive-procedures (list (list ‘car car) (list ‘cdr cdr) (list ‘cons cons) (list ‘null? null?) (list ‘eq? eq?) (list ‘map map)))
因为我们的 eval 的底层的表示与宿主语言 scheme 的表示并不是一样的。
当我们使用
(eval '(map (lambda (x) (+ x 1)) '(1 2 3 4)) the-global-environment)
的时候, eval 将
- 发现这是一个过程调用
- 发现这是一个基本过程(primitive procedure)调用,将使用 apply 中的 apply-in-undering-scheme 过程来求值
对参数进行求值
- (lambda (x) (+ x 1)) 将变为
'(procedure (x) (+ x 1) <procedure env>)
'(1 2 3 4)
即'(1 2 3 4)
- (lambda (x) (+ x 1)) 将变为
- 将参数与过程的形式参数(formal parameter)进行绑定,创造出一个 environment。即会把
'(1 2 3 4)
绑定到 map 的第二个参数上,准备提供给代表一个过程的第一个参数使用;把'(procedure (x) (+ x 1) <procedure env>)
绑定到第一个参数上。 - 使用宿主语言的 apply 过程来求值,即
(apply map '((procedure (x) ((+ x 1)) <procedure env>) (1 2 3 4)))
看到这里的时候,我们就发现了,如果直接使用宿主语言的 map,那我们的 eval 得到的对象将被传递给那个 map。因为宿主语言过程的表示形式和我们使用的不一样,导致了出错。
;The object (procedure (x) ((+ x 1)) (((false true car cdr cons null? eq? map = +) #f #t (primitive #[compiled-procedure 2 ("list" #x1) #x3 #x4d2a2]) (primitive #[compiled-procedure 3 ("list" #x2) #x3 #x4d29b]) (primitive #[compiled-procedure 4 ("list" #x3) #x3 #x4d295]) (primitive #[compiled-procedure 5 ("list" #x5) #x3 #x4d286]) (primitive #[compiled-procedure 6 ("global" #x14) #x3 #x480ab]) (primitive #[compiled-procedure 9 ("list" #x6f) #x7 #x4caef]) (primitive #[arity-dispatched-procedure 7]) (primitive #[arity-dispatched-procedure 8])))) is not applicable.
;To continue, call RESTART with an option number:
; (RESTART 2) => Specify a procedure to use in its place.
; (RESTART 1) => Return to read-eval-print level 1.
所以,我们只能把 map 当做一个 compound procedure 来定义,而不能把它定义为 primitive procedure。当 map 是一个 compound procedure 的时候,我们就能让 map 识别出 (procedure (x) ....) 是一个 procedure。