Common Lisp:如何使用条件拼接在宏中构建列表? [英] Common Lisp: How to build a list in a macro with conditional splicing?

查看:72
本文介绍了Common Lisp:如何使用条件拼接在宏中构建列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们假设:

(defmacro testing (&optional var)
    `(list 'this 'is  
       ,@(when (consp var) `('a 'list))))

在致电时

>(testing 2)
(THIS IS)

>(testing (list 1 2))
(THIS IS A LIST)

这就是我想要的.但是现在,当我传递一个作为列表的参数时:

which is what I wanted. But now, when I pass a parameter that is a list:

>(defparameter bla (list 1 2 3))
BLA
>(testing bla)
(THIS IS)

我想这是因为宏会检查(consp bla),其中bla是符号,而不是列表?我该如何预防?

which I suppose is because the macro would check (consp bla) where bla is a symbol, instead of the list? How do I prevent this?

谢谢

推荐答案

您可以执行以下操作:

(defmacro testing (&optional var)
   `(if (consp ,var)
        '(this is a list)
        '(this is)))

因此,var将在运行时(而非编译时)进行求值. var在宏的扩展中只出现一次,但是如果它出现不止一次,则必须使用gensym.

So var will be evaluated at run time (not compile time). var only appears one time in the expansion of the macro, but if it appeared more than once, you would have to use a gensym.

如果您不想两次键入'(this is),请执行以下操作:

If you don't want to type '(this is) twice, do this:

(defmacro testing (&optional var)
  `(append '(this is) (when (consp ,var) '(a list))))

不要使用eval,它很慢,而且完全没有必要.通过将var替换为宏扩展,自然可以在运行时对其进行评估.如果使用eval,则将执行以下操作:

Don't use eval, it's slow, and completely unnecessary. By substituting var into the macro expansion, it will naturally be evaluated at run-time. If you use eval, you will be doing something like this:

(eval (append '(list 'this 'is) (when (consp 'bla) '('a 'list))))

次执行,它将建立一个代表代码的列表,并在运行之前对其进行编译. (希望这不是循环的!)如果您仅使用可生成简单代码(不带eval)的宏,则它将仅编译一次.

Every time that executes, it will build up a list representing the code and compile it before running it. (Hopefully this isn't in a loop!) If you just use a macro which generates straightforward code (without eval), it will compile only once.

这篇关于Common Lisp:如何使用条件拼接在宏中构建列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆