Когда вы делаете:
(define x '(lambda (n) (+ n 1)))
Вы делаете привязку x
, чтобы указать на структуру списка (lambda (n) (+ n 1))
.Он не имеет ничего общего с lambda
формами, такими как:
(define x2 (lambda (n) (+ n 1)))
, где вы можете применить (x2 1) ; ==> 2
, поскольку его значение является замыканием / процедурой / функцией, поскольку вычисляется лямбда-форма.
(lambda (cadr x)(caddr e))
не оценивает (cadr x)
, скорее, он создает замыкание с формальными параметрами cadr
и x
, так что вы можете применить результат ((lambda (cadr x) ...) 1 2)
так, чтобы оценка cadr
взакрытие становится 1
, а x
становится 2
.Оценка (caddr e)
происходит, когда вы подаете заявку, поэтому, если вы позвоните ((lambda (cadr x)(caddr e)) 'ignored1 'ignored2)
, она вернет то же, что и оценка (caddr e)
в среде, в которой было создано закрытие.Было бы невозможно заставить работать (eval `(lambda ,(cadr x) ,(caddr e)))
, поскольку у вас не будет возможности обрабатывать свободные переменные, поскольку вы смешиваете хост с вашим гостем.
Поскольку вы создаете интерпретатор, ваши пользовательские процедуры будут структурами данных, и ваш apply
будет знать, что с ним делать.Оценка формы должна возвращать что-то, что может быть идентифицировано как замыкание, и вы не можете сделать какой-либо другой код в своем интерпретаторе, чтобы обмануть ее, имеет ссылку на лексическую область места, где она была оценена, и на каждую часть cdr
если лямбда.
Один из моих делает это:
(define closure-tag (list 'closure)) ; make something that is not `eq?` with enything else
(define (closure? expr)
(and (pair? expr)
(eq? closure-tag (car expr))))
(define (lambda->closure expr env)
`(,closure-tag ,env ,@(cdr expr)))
Таким образом, оценка лямбды (lambda (n) (+ n 1))
становится ((closure) ((#t . #t) ...) (n) (+ n 1))
и применяется для ((lambda (n) (+ n 1)) 2)
, оценивает (+ n 1)
с окружающей средой ((n . 2) (#t . #t) ...)
.Выбор структуры не имеет значения, поскольку структура является соглашением между оценкой лямбда-формы и вашей заявкой.
Вы можете сделать формы lambda
процедурами, но это все же не хост-версия гостевого источника, а своего рода оптимизация.Один из моих последних eval
сделал это и взял всегда 2 аргумента.Список аргументов неоценен и окружением.В eval
lingo примитивы были карри с evlis
и apply
.Большинство вариантов дизайна, которые вы делаете, будут иметь как преимущества, так и недостатки, и с ними интересно играть.