Đây là cả hơn, ít hơn và nghiêng tới hơn bạn muốn:
(define (make-let-core name value body)
`(CORE LET ,name ,value ,body))
(define (env-extend env a-name its-denotation)
(lambda (name)
(if (equal? name a-name)
its-denotation
(if env (env name) 'unknown))))
(define (env-base)
(lambda (name)
(if (member name '(let resolve-sym #| ... |#))
'syntactic-keyword
'unknown)))
(define (expand exp env)
(cond ((literal? exp) ...)
((symbol? exp) ...)
((list? exp)
(let ((operator (car exp))
(operands (cdr exp)))
(cond ((symbol? operator)
(case (env operator)
((syntactic-keyword)
(case operator
((let)
(let ((bound-name (caar operands))
(bound-value (cadar operands))
(body (cdr operands)))
(make-let-core bound-name
(expand bound-value env)
(expand body
(env-extend bound-name
'variable)))))
((resolve-sym)
(let ((name (car operands)))
;; right here
...))
(...)))
((variable) ;; function call
...)
((unknown) ;; syntax error
...)))
((list? operator) ;; function call
...)
(else ;; syntax error
...))))
(else ;; syntax error
...)))
Hãy không tạo ra vars mới, vì vậy về cơ bản bạn không thể giải quyết chúng – Ankur
Nhưng nó có thể để có được môi trường bên trong một macro với & env. – navgeet
@navgeet, không, điều đó là không thể. '(defmacro m [x & env] '(x env))' sẽ mở rộng theo cách này: '(m 1 2 3 4 5) ->' (1 (2 3 4 5))', tức là '& env' sẽ cung cấp cho bạn quyền truy cập vào varargs. Không có cách nào trong Clojure để có được môi trường từ vựng hiện tại. –