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
.