Lisp 试图使宏类似于defparameter,defvar,但宏仅返回s表达式

Lisp 试图使宏类似于defparameter,defvar,但宏仅返回s表达式,lisp,common-lisp,Lisp,Common Lisp,我试图制作宏来定义各种对象,类似于defparameter和defvar。defregion1宏起作用:在执行时,它使用objectregion定义一个变量。但是,defregion2仅返回必须手动执行的表达式。代码如下: (defclass location () ((x :initarg :x :accessor x) (y :initarg :y :accessor y))) (defclass region () ((x :initarg

我试图制作宏来定义各种对象,类似于
defparameter
defvar
defregion1
宏起作用:在执行时,它使用object
region
定义一个变量。但是,
defregion2
仅返回必须手动执行的表达式。代码如下:

(defclass location ()
  ((x
    :initarg :x
    :accessor x)
   (y
    :initarg :y
    :accessor y)))

(defclass region ()
  ((x :initarg :x
      :accessor x)
   (y :initarg :y
      :accessor y)
   (w :initarg :w
      :accessor w)
   (h :initarg :h
      :accessor h)))

(defmacro deflocation (var x y)
  `(defparameter ,var `(make-instance 'location :x ,x :y ,y)))


(defmacro defregion1 (var x y w h)
  `(defparameter ,(intern (symbol-name var))
       (make-instance 'region :x ,x :y ,y :w ,w :h ,h)))

(defmacro defregion2 (var l1 l2)
  `(with-slots ((x1 x) (y1 y))
       ,l1
     (with-slots ((x2 x) (y2 y))
         ,l2
       `(defparameter ,(intern (symbol-name ,var))
           (make-instance 'region
                          :x ,x1 :y ,y1 :w (- ,x2 ,x1) :h (- ,y2 ,y1))))))
defregion1
的输出:

(defregion1 *test-reg1* 1 2 3 4) 

=> *test-reg1*
延迟区域2的输出:

(deflocation *l1* 20 30)
(deflocation *l2* 50 60)
(defregion2 '*test-reg2* *l1* *l2*)

=> (DEFPARAMETER *TEST-REG2*
     (MAKE-INSTANCE 'REGION :X 20 :Y 30 :W (- 50 20) :H (- 60 30)))

我希望
*test-reg2*
也成为一个变量。这里怎么了?

您有两个嵌套的反引号

但您的宏也是由内而外的:您确实希望
defparameter
处于顶层,因此这样做会更好:

(defmacro defregion2 (var l1 l2)
  `(defparameter ,(intern (symbol-name ,var)) 
     (with-slots ((x1 x) (y1 y))
         ,l1
       (with-slots ((x2 x) (y2 y))
           ,l2
         (make-instance 'region :x x1 :y y1 :w (- x2 x1) :h (- y2 y1))))))
还有,你确定你想要这个有点奇怪的内室吗?这将要做的是将您给出的符号的名称作为参数,并在当前包中插入它。比如说

(defregion2 x:*foo* ...)
将导致当前包中出现符号
*foo*
,而不是给
x:*foo*
赋值。(当然,如果当前包是
x
,那么所有这些都会折叠成同一个东西)

我想你可能想要

(defmacro defregion2 (var l1 l2)
  `(defparameter ,var
     (with-slots ((x1 x) (y1 y))
         ,l1
       (with-slots ((x2 x) (y2 y))
           ,l2
         (make-instance 'region :x x1 :y y1 :w (- x2 x1) :h (- y2 y1))))))
您的代码也可能不卫生,因为它将变量(实际上是符号宏)绑定到对
l2
可见的名称:这样会更安全

(defmacro defregion2 (var l1 l2)
  `(defparameter ,var
     (let ((l1 ,l1) (l2 ,l2))
       (with-slots ((x1 x) (y1 y))
           l1
         (with-slots ((x2 x) (y2 y))
             l2
           (make-instance 'region :x x1 :y y1 :w (- x2 x1) :h (- y2 y1)))))))
现在可以从扩展中看到,这是安全的:

(defregion2 *thing* 
            (expression-involving x1 x2)
            (another-expression-involving x1 x2))
扩展到

(defparameter *thing*
  (let ((l1 (expression-involving x1 x2))
        (l2 (another-expression-involving x1 x2)))
    (with-slots ((x1 x) (x2 y)) l1
      (with-slots ((x2 x) (y2 y)) l2
        (make-instance 'region :x x1 :y y1 :w (- x2 x1) :h (- y2 y1))))))

您可以看到
中的
x1
(另一个涉及x1…
的表达式不是由
与插槽绑定的表达式

谢谢。至于
intern
,它一直在对未绑定变量求值,所以我尝试修复它。但这似乎是嵌套反报价的问题。