代码之家  ›  专栏  ›  技术社区  ›  hawkeye

给定以下lisp eval函数-添加defmacro需要什么?

  •  26
  • hawkeye  · 技术社区  · 14 年前

    给出以下内容 definition 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)) )
    
    2 回复  |  直到 14 年前
        1
  •  21
  •   DomQ    14 年前

    按照惯例,匿名宏的表示形式是 (macro lambda ...) . 尝试在您最喜欢的Lisp解释器(在Emacs中测试)中回避这些问题:

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

    三倍的

    > (符号功能‘三重’)

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

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

    1. 替换所有出现的 x 在里面 FORM 具有 EXPR 没有 评价 EXPR 首先(与函数调用中发生的情况相反);
    2. 埃瓦 以上结果。

    您可以通过向最外层添加子句来实现这一点。 cond 在里面 埃瓦 它处理的是 ((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. 但是没有循环到 埃瓦 ;这是留给读者的练习:—)

    测试,定义 cadr. 从宏观上看:

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

    在这之后你会

    > (符号函数'cadr.)

    (宏lambda(x)(列表。(引用汽车)(列表。(引用cdr)x)))

    您可以构造一个应用此 (宏lambda…) 到表达式,并在包含 list. (因为它不被认为是原始的 埃瓦 解释器)。例如,

    (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))
    

    Y

    塔达!

        2
  •  3
  •   luser droog    8 年前

    这也很好: https://web.archive.org/web/20120702032624/http://jlongster.com/2012/02/18/its-not-about-macros-its-about-read.html

    “您可以在30行lisp中实现一个宏系统。你所需要的只是阅读,这很容易。” https://gist.github.com/1712455