haw*_*eye 26 lisp macros eval common-lisp
给定LISP eval函数的以下定义 - 添加defmacro函数需要什么?(甚至只是评估一个宏)
(defun null. (x)
(eq x '()))
(defun and. (x y)
(cond (x (cond (y 't) ('t '())))
('t '())))
(defun not. (x)
(cond (x '())
('t 't)))
(defun append. (x y)
(cond ((null. x) y)
('t (cons (car x) (append. (cdr x) y)))))
(defun list. (x y)
(cons x (cons y '())))
(defun pair. (x y)
(cond ((and. (null. x) (null. y)) '())
((and. (not. (atom x)) (not. (atom y)))
(cons (list. (car x) (car y))
(pair. (cdr x) (cdr y))))))
(defun assoc. (x y)
(cond ((eq (caar y) x) (cadar y))
('t (assoc. x (cdr y)))))
(defun eval. (e a)
(cond
((atom e) (assoc. e a))
((atom (car e))
(cond
((eq (car e) 'quote) (cadr e))
((eq (car e) 'atom) (atom (eval. (cadr e) a)))
((eq (car e) 'eq) (eq (eval. (cadr e) a)
(eval. (caddr e) a)))
((eq (car e) 'car) (car (eval. (cadr e) a)))
((eq (car e) 'cdr) (cdr (eval. (cadr e) a)))
((eq (car e) 'cons) (cons (eval. (cadr e) a)
(eval. (caddr e) a)))
((eq (car e) 'cond) (evcon. (cdr e) a))
('t (eval. (cons (assoc. (car e) a)
(cdr e))
a))))
((eq (caar e) 'label)
(eval. (cons (caddar e) (cdr e))
(cons (list. (cadar e) (car e)) a)))
((eq (caar e) 'lambda)
(eval. (caddar e)
(append. (pair. (cadar e) (evlis. (cdr e) a))
a)))))
(defun evcon. (c a)
(cond ((eval. (caar c) a)
(eval. (cadar c) a))
('t (evcon. (cdr c) a))))
(defun evlis. (m a)
(cond ((null. m) '())
('t (cons (eval. (car m) a)
(evlis. (cdr m) a)))))
(eval '(car '(a a)) )
Run Code Online (Sandbox Code Playgroud)
Dom*_*omQ 21
按照惯例,匿名宏的表示形式是表单的列表(macro lambda ...).尝试在您最喜欢的Lisp解释器中进行评估(在Emacs中测试):
>(defmacro triple(x)`(+,x,x,x))
三倍
>(符号功能'三联)
(宏lambda(x)(\`(+(\,x)(\,x)(\,x))))
虽然事情在Emacs中不起作用,但唯一要做的就是给这样一个表单提供足够的语义.也就是说,当eval.看到((macro lambda (x) EXPR) FORM)它时,它必须
x在FORM与EXPR 无评价EXPR第一(而不是在函数调用会发生什么);eval. 结果如上.您可以通过cond在eval.处理((macro lambda ...) ...)案例的最外层添加一个子句来实现此目的.这是一个粗略的原型:
((eq (caar e) 'macro)
(cond
((eq (cadar e) 'lambda)
(eval. (eval. (car (cdddar e))
(cons (list. (car (caddar e)) (cadr e)) a))
a))))
Run Code Online (Sandbox Code Playgroud)
此代码仅适用于单参数宏.修复涉及编写一个substlis.类似evlis.但没有循环的辅助函数eval.; 留给读者的练习:-)
要进行测试,cadr.请将其定义为宏:
(defmacro cadr. (x)
(list. 'car (list. 'cdr x)))
Run Code Online (Sandbox Code Playgroud)
在此之后你会有
>(符号功能'cadr.)
(macro lambda(x)(list.(报价车)(list.(引用cdr)x)))
您可以构造一个将其应用于(macro lambda ...)表达式的表单,并在包含定义的上下文中评估该构造list.(因为它不被eval.解释器视为原始的).例如,
(let ((e '((macro lambda (x) (list (quote car) (list (quote cdr) x)))
(cons (quote x) (cons (quote y) nil))))
(bindings `((list ,(symbol-function 'list.)))))
(eval. e bindings))
Run Code Online (Sandbox Code Playgroud)
ÿ
田田!