-2

我需要为可以读取此语法的元循环解释器创建函数 defmacro:

pseudoscheme> (defmacro (minus x y) (list ‘- y x))
MINUS


pseudoscheme> (expand-macro '(minus 3 2))
(- 3 2)

当我使用这个时:

(defmacro my-defmacro ((name &rest args) &body  body)
    (let ((form (gensym))(env (gensym)))
        (progn 
        `(setf (macro-function ',name)    
            (lambda (,form ,env))
                (destructuring-bind ,args (rest, form) ,@body))
        name
        )   
    )
)

接着:

(my-defmacro (min a b)(list '- a b))

我收到此错误:

Error: The variable MIN is unbound.

我不明白为什么。

-----已编辑----- 如果我使用这个:

(defmacro my-defmacro ((name &rest args) &body  body)
    (let ((form (gensym))(env (gensym)))
        `(progn (setf (macro-function ',name)
            (lambda (,form ,env))
                (destructuring-bind ,args (rest, form) ,@body))
         ',name)    
    )
)

接着:

(my-defmacro (min a b)(list '- a b))

我收到此错误:

Error: Odd number of args to SETF: ((MACRO-FUNCTION (QUOTE PLUS)) (LAMBDA (#:G786 #:G787)) (DESTRUCTURING-BIND (A B) (REST #:G786) (LIST # A B)))
4

2 回答 2

0

对于您的“已编辑代码”,您有一个错误的括号:

(defmacro my-defmacro ((name &rest args) &body  body)
    (let ((form (gensym))(env (gensym)))
        `(progn (setf (macro-function ',name)
            (lambda (,form ,env))                    ;; <== HERE
                (destructuring-bind ,args (rest, form) ,@body))
         ',name)    
    )
)

这导致setf具有三个子表单。像这样重写它(同时使用标准的 Lisp 格式):

(defmacro my-defmacro ((name &rest args) &body  body)
  (let ((form (gensym))
        (env  (gensym)))
    `(progn (setf (macro-function ',name)
                  (lambda (,form ,env)
                    (destructuring-bind ,args (rest, form) 
                      ,@body)))
            ',name)))   
于 2013-09-29T15:59:19.930 回答
0

您的my-defmacro作品为您托管 CL 系统,但我感觉您希望在解释器中具有宏功能,但这样做不会。(除非解释器环境是全局主机实现环境,但这会带来很多挑战)

我不知道您如何在评估器中执行复合程序,但是当我的评估器得到 a 时(lambda (x) (+ x x)),它会变成(compound-procedure <env> (x) (+ x x)). 我的宏变成几乎一样除了第一个元素是compound-syntax.

每个评估的运算符都有一个标签,告诉它它是什么(原始语法,原始过程,复合语法,复合过程之一),我只需要处理这 4 个的一般方法。

复合过程和复合语法之间的真正区别在于,参数被评估为过程,而在复合语法中,结果被评估。

所以。您是否已实现 ((lambda (x) (+ xx)) 5) 工作?好吧,那么您几乎也将实现宏。对于编译器来说当然不是这样,因为这种方法会在每次运行时扩展代码,而不是在创建闭包时扩展一次。(优化是没有办法继续第一个版本)

于 2013-09-29T00:38:42.153 回答