我需要为我的元循环解释器创建函数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.
我无法理解为什么。
- - - - - - - - EDITED 如果我用这个:
(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)))
答案 0 :(得分:0)
您的my-defmacro
适用于托管CL系统,但我觉得您希望在解释器中使用宏功能,但这样做不会。 (除非解释器环境是全局主机实现环境,否则会带来很多挑战)
我不知道你在评估员中如何进行复合程序,但当我的评估者得到(lambda (x) (+ x x))
时,它变成了(compound-procedure <env> (x) (+ x x))
。我的宏变成几乎相同,除了第一个元素是compound-syntax
。
每个被评估的运算符都有一个标记,告诉它它是什么(原始语法,原始过程,复合语法,复合过程之一),我只需要处理那些4的一般方法。
复合过程和复合语法之间的真正区别在于,为过程评估参数,并在复合语法中评估结果。
因此。你实现了((lambda(x)(+ x x))5)有效吗?好吧,那么你几乎也会实现宏。对于编译器来说当然不是这样,因为这种方法会在每次运行时扩展代码,而不是在创建闭包时扩展一次。 (无论如何,优化都无法进入第一个版本)
答案 1 :(得分:0)
对于你的“编辑过的代码”,你有一个错位的paren:
(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)))