使用 lisp 宏生成多语句代码
根据我的理解,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。
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您必须了解编译时间和评估时间之间的区别。
该宏在编译时展开,并且引用的所有内容都按原样插入到源代码中(不进行评估)。因此
(macroexpand-1 '(myMac2 1 2 3))
将产生(mapcar (lambda (sw) (myMac2 1 sw)) 2 3)
(另请注意, 你必须使用&rest
代替@rest
。如果你想获得
mapcar
的结果, ,那个形式不应该被引用:但这不是一个有效的形式,你想要的是
(list (myMac1 1 2) (myMac1 1 3))
。 list 围绕生成的表单(为什么你应该在这里使用,@
留作练习;)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:But this isn't a valid form. What you want is
(list (myMac1 1 2) (myMac1 1 3))
. To achieve that you have to wraplist
around the generated forms (why you should use,@
here is left as an exercise for though ;)