Macros 使用lisp宏生成多语句代码

Macros 使用lisp宏生成多语句代码,macros,lisp,Macros,Lisp,据我所知,LISP中宏的一个用法是生成所需的代码 我有以下主体代码: (list (list "aVar" "Hi") (list "bVar" 10) (list "addSW1" (equal dpl->addSW1)) ... (list "addSW100" (equal dpl->addSW100))) 因此,基本上我正在尝试编写宏,为SW1到SW100生成代码,这样我就不需要写100行了 我创建了我的第一个宏: (de

据我所知,LISP中宏的一个用法是生成所需的代码

我有以下主体代码:

(list (list "aVar" "Hi")
      (list "bVar" 10)
      (list "addSW1" (equal dpl->addSW1)) 
      ...
      (list "addSW100" (equal dpl->addSW100))) 
因此,基本上我正在尝试编写宏,为
SW1
SW100
生成代码,这样我就不需要写100行了

我创建了我的第一个宏:

(defmacro myMac1 (dpl sw)
 `(list ,switchStr "boolean" (equal "Y" (get ,dpl ,sw))))
这对我来说很有用,所以我现在可以做
(myMac1“addSW1”)
,它将生成一个列表语句

然后,我创建了第二个mac:

(defmacro myMac2 (dpl @rest allSwitches)
 `(mapcar (lambda (sw)
            (myMac1 ,dpl sw))
          ,@allSwitches))
所以,如果我写
(myMac2 dpl“addSW1”“addSW2”…“addSW100”)
它将产生:

(list (list "addSW1" (equal dpl->addSW1)) 
      ... till 100))
但是,在主体代码中,我不想要列表的列表。我只想要100张名单


有解决办法吗?抱歉,描述太长了:P.

您必须理解编译时和计算时之间的区别

宏在编译时展开,引用的所有内容都按原样插入到源代码中(无需计算)。因此
(macroexpand-1'(myMac2 1 2 3))
将产生
(mapcar(lambda(sw)(myMac2 1 sw))2 3)
(还要注意,您必须使用
&rest
代替
@rest

如果要获得
mapcar
的结果,不应引用该表单:

(defmacro myMac2 (dpl &rest allSwitches)
  (mapcar (lambda (sw)
            `(myMac1 ,dpl ,sw))
          allSwitches))
(macroexpand-1 '(myMac2 1 2 3)) => ((myMac1 1 2) (myMac1 1 3))
但这不是一个有效的表单。您需要的是
(list(myMac1 2)(myMac1 3))
。要实现这一点,您必须将
列表
包装在生成的表单周围(为什么要使用
,@
此处作为练习;)


感谢您在这方面的帮助。由于我从列表中调用此宏,我希望(myMac1 2)(myMac1 3)作为我的最终解决方案,但不是它们的列表。给定的第二个解决方案生成两个myMac1的列表。是否可以仅获取(myMac1 2)(myMac1 3)。我也尝试了您的第一个解决方案,但出现错误:error eval:not a function-(myMac1 2)。顺便说一句,这是scheme方言。Cadence技巧。在这里,如果是Lisp或scheme,这并不重要。回答您关于获取
(myMac1 1 2)(myMac1 1 3)
:1个宏可以生成1项(原子、列表或其他对象)。从技术上讲,您无法获取2项,但可以将它们嵌套在一个特殊的运算符中,该运算符在Lisp中称为
progn
,在Scheme中称为
begin
。这就是需要
,@
的地方:它需要一个列表(宏的输出)然后将其“拼接”到包装器表单中。但是应该有一个包装器表单,在您的情况下,它将是
开始
。但是请注意,这样您将丢失调用
列表
的所有结果,但最后一个结果除外。
(defmacro myMac2 (dpl &rest allSwitches)
  `(list ,@(mapcar (lambda (sw)
                    `(myMac1 ,dpl ,sw))
                   allSwitches)))
(macroexpand-1 '(myMac2 1 2 3)) => (list (myMac1 1 2) (myMac1 1 3))