使用 lisp 宏生成多语句代码

发布于 2024-12-10 07:05:30 字数 928 浏览 0 评论 0原文

根据我的理解,LISP 中宏的用法之一是生成所需的代码。

我有以下主体代码:

(list (list "aVar" "Hi")
      (list "bVar" 10)
      (list "addSW1" (equal dpl->addSW1)) 
      ...
      (list "addSW100" (equal dpl->addSW100))) 

所以,基本上我正在尝试编写为 SW1SW100 生成代码的宏,这样我就不需要编写 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。

As per my understanding one of the usage of macro in LISP is to generate desired code.

I have following main body code:

(list (list "aVar" "Hi")
      (list "bVar" 10)
      (list "addSW1" (equal dpl->addSW1)) 
      ...
      (list "addSW100" (equal dpl->addSW100))) 

So, basically I am trying to write macros that generate code for SW1 to SW100 so that I dont need to write 100 lines.

I created my 1st macro:

(defmacro myMac1 (dpl sw)
 `(list ,switchStr "boolean" (equal "Y" (get ,dpl ,sw))))

That worked for me and so I can now do (myMac1 "addSW1") that will generate single list statement.

Then, I created 2nd mac:

(defmacro myMac2 (dpl @rest allSwitches)
 `(mapcar (lambda (sw)
            (myMac1 ,dpl sw))
          ,@allSwitches))

So, if I write (myMac2 dpl "addSW1" "addSW2" ... "addSW100")
It will generate:

(list (list "addSW1" (equal dpl->addSW1)) 
      ... till 100))

But, in main body code I don't want list of list. I just wanted 100 lists.

Any solution? Sorry for very long description :P.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

缺⑴份安定 2024-12-17 07:05:30

您必须了解编译时间和评估时间之间的区别。

该宏在编译时展开,并且引用的所有内容都按原样插入到源代码中(不进行评估)。因此 (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 1 2) (myMac1 1 3))。 list 围绕生成的表单(为什么你应该在这里使用 ,@ 留作练习;)

(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))

You have to understand the difference between compile time and evaluation time.

The macro is expanded at compile time and everything, that is quoted, is inserted into the source code as is (without evaluation). So (macroexpand-1 '(myMac2 1 2 3)) will yield (mapcar (lambda (sw) (myMac2 1 sw)) 2 3) (Also note, that you have to use &rest in place of @rest.

If you want to get the result of mapcar, that form shouldn't be quoted:

(defmacro myMac2 (dpl &rest allSwitches)
  (mapcar (lambda (sw)
            `(myMac1 ,dpl ,sw))
          allSwitches))
(macroexpand-1 '(myMac2 1 2 3)) => ((myMac1 1 2) (myMac1 1 3))

But this isn't a valid form. What you want is (list (myMac1 1 2) (myMac1 1 3)). To achieve that you have to wrap list around the generated forms (why you should use ,@ here is left as an exercise for though ;)

(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))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文