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

Macros 给定以下LISP eval函数-添加defmacro需要什么?,macros,lisp,common-lisp,eval,Macros,Lisp,Common Lisp,Eval,给定以下LISP eval函数-添加defmacro函数需要什么?(甚至只是计算宏) 按照惯例,匿名宏的表示形式为(宏lambda…的列表。尝试在您最喜欢的Lisp解释器(在Emacs中测试)中计算这些值: (反宏三元组(x)`(+,x,x,x)) 三重 (符号功能“三重”) (宏lambda(x)(\`(+(\,x)(\,x)(\,x))) 尽管在Emacs中事情不是这样的,但唯一要做的就是为这种形式提供足够的语义。也就是说,当eval.看到((宏lambda(x)EXPR)表单)时,它必须

给定以下LISP eval函数-添加
defmacro
函数需要什么?(甚至只是计算宏)


按照惯例,匿名宏的表示形式为
(宏lambda…
的列表。尝试在您最喜欢的Lisp解释器(在Emacs中测试)中计算这些值:

(反宏三元组(x)`(+,x,x,x))

三重

(符号功能“三重”)

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

尽管在Emacs中事情不是这样的,但唯一要做的就是为这种形式提供足够的语义。也就是说,当
eval.
看到
((宏lambda(x)EXPR)表单)
时,它必须

  • 表单中出现的
    x
    替换为
    EXPR
    ,而不首先对
    EXPR
    求值(与函数调用中发生的情况相反)
  • eval.
    上述结果
  • 您可以通过在
    eval.
    中最外层的
    cond
    中添加一个子句来实现这一点,该子句处理
    ((宏lambda…)
    案例。这是一个粗略的原型:

    ((eq (caar e) 'macro)
         (cond
          ((eq (cadar e) 'lambda)
           (eval. (eval. (car (cdddar e))
                         (cons (list. (car (caddar e)) (cadr e)) a))
                  a))))
    
    此代码仅适用于单参数宏。修复此问题需要编写一个辅助函数
    substris.
    ,该函数的工作原理类似于
    evlis.
    ,但不会循环到
    eval.
    ;这是留给读者的练习:-)

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

    (defmacro cadr. (x)
      (list. 'car (list. 'cdr x)))
    
    在这之后你会

    (符号功能“cadr.”

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

    您可以构造一个表单,将此
    (宏lambda…
    应用于表达式,并在包含
    列表定义的上下文中对该构造进行求值。
    (因为
    求值。
    解释器不认为它是原始的)。比如说,

    (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

    塔达

    这也很好:

    “你可以用30行Lisp语言实现一个宏系统。你所需要的只是阅读,而且很容易。”

    谢谢@DomQ-但我在中尝试您的解决方案的两个LISP环境会产生堆栈溢出。您的解决方案中是否可能存在问题?导致溢出的“assoc”中有一个bug,请尝试evaling(assoc.“x nil”)。您可以通过在“assoc.”的cond块中添加一个子句来修复它,该子句的内容为:((null.y))()。我给Paul Graham发了电子邮件,他说这不是一个bug,因为原作者John McCarthy并不关心错误的程序(即那些在“eval”中引用自由变量的程序)。无论如何,您观察到的堆栈溢出可能只是另一个问题的症状。尝试使用(包含“assoc.”修复程序和我对您的问题的解决方案;使用Emacs 22和librep.sf.net进行测试)。这是另一个示例
    (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))