如果我遇到原始程序,我是否总是使用基础方案申请?
假设我这样做,我将如何重新实施申请方案解释器来解释自己?
(define apply-1
(lambda (proc args)
(cond ((primitive? proc)
(apply proc args)) <-- How would I reimplement this
((eq? (car proc) 'closure)
(eval (cadr (cadr proc))
(bind (car (cdr proc)) args (caddr proc))))
(else error))))
答案 0 :(得分:1)
Primitive-apply是解释器中的原语如何与底层实现实现之间的粘合剂。使用主机apply
来应用基本系统中确实是过程的原语是一种技巧。您无法创建主机apply
,但您可以使用interpreter
原语 - 以不同的方式应用,或者支持其他方式来封装基元。例如
;; define representations for primitives
(define prim-cons (list 'cons)) ; system unique
(define prim-car (list 'car))
...
;; define primitive?
(define (primitive? proc)
(or (eq? proc prim-cons)
(eq? proc prim-car)
...))
;; define primitive apply
(define (primitive-apply proc args)
(cond ((eq? proc prim-cons) args)
((eq? proc prim-car) (caar args))
...))
;; boot environment
(define primitive-environment
(list (cons #t prim-true)
(cons #f prim-false)
(cons '() prim-null)
(cons 'cons prim-cons)
(cond 'car prim-car)
...))
事实是使用apply
只是一种简化,因为实际的原始过程是已解析的对象。它并不总是那样。想象一下,我们尝试优化它:
;; define representations for primitives
(define prim-cons (list 'cons)) ; system unique
(define prim-car (list 'car))
;; make a list of primitives and their implementation
(define primitives
(list (cons prim-cons values)
(cons prim-car caar)))
;; define primitive?
(define (primitive? proc)
(assq proc primitives))
;; make apply-primitive
(define (apply-primitive proc args)
((cdr (primitive? proc)) args))
仍有很多样板..为什么不将整个原始列表移动到环境中。
;; make tags
(define *primitive* (list 'primitive))
(define *constant* (list 'constant))
;; make a list of primitives and their implementation
(define boot-env
(list (list* 'cons *primitive* values)
(list* 'cons *primitive* caar)
...
(list* #f *constant* #f)
(list* #t *constant* #t)))
;; verify type
(define (is-type? x type)
(and (pair? proc)
(eq? (car proc) type)))
;; define primitive?
(define (primitive? proc)
(is-type proc *primitive*))
(define (constant? x)
(is-type x *constant*))
;; make apply-primitive
(define (apply-primitive proc args)
((cdr proc) args))
现在。对于复合程序,我们只有类似的标签。 eval
本身变得非常小,因为您甚至可以在您的环境中使用*special-form*
来执行类似的操作,使您的eval
仅在您评估的值类型之间进行案例分析,而不是特殊情况。
我对apply
的一个想法是,当我从解释器调用过程apply
时,我希望我的apply
成为被调用者。您可以使用apply
,但apply
实际上也需要由apply
处理。当你尝试申请eval
时,你会遇到同样奇怪的事情。