鉴于以下LISP评估功能 - 添加defmacro需要什么?

时间:2010-09-10 09:05:48

标签: macros lisp common-lisp eval

鉴于LISP eval函数的以下definition - 添加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)) )

1 个答案:

答案 0 :(得分:21)

匿名宏的表示按照惯例是(macro lambda ...)形式的列表。尝试在你最喜欢的Lisp解释器中进行评估(在Emacs中测试):

> (defmacro triple(x)`(+,x,x,x))

三重

> (符号功能'三联)

(宏lambda(x)(\`(+(\,x)(\,x)(\,x))))

虽然事情在Emacs中不起作用,但唯一要做的就是给这样一个表单提供足够的语义。也就是说,当eval.看到((macro lambda (x) EXPR) FORM)时,它必须

  1. xFORM的每次出现替换为EXPR 而不首先评估EXPR(与函数调用中发生的情况相反) ;
  2. eval.上述结果。
  3. 您可以通过在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))))
    

    此代码仅适用于单参数宏。修复涉及编写一个与substlis.类似但不循环到evlis.的辅助函数eval.;留给读者的练习: - )

    要进行测试,请将cadr.定义为宏:

    (defmacro cadr. (x)
      (list. 'car (list. 'cdr x)))
    

    在此之后你会有

    > (symbol-function'cadr。)

    (macro lambda(x)(list。(报价车)(list。(引用cdr)x)))

    您可以构造一个将此(macro lambda ...)应用于表达式的表单,并在包含list.定义的上下文中评估该构造(因为它不被{{1}视为原始的解释者)。例如,

    eval.

    ý

    多田!