我有:
(defmacro test (a b c)
`'(,a ,b ,c))
正常运行(test apple banana cuba)
可获得(APPLE BANANA CUBA)
。
如何让宏制作APPLEBANANACUBA?
我试过了:
(defmacro test (a b c)
`'(,a,b,c))
但正在运行(test ant bites chris)
仍会返回(ANT BITES CHRIS)
作为三个单独args的列表。
我尝试了各种变体,但似乎都没有效果。像这样:
(defmacro test (a b c)
`(apply #'concatenate 'symbol '(,a ,b ,c)))
显然,这会出错,因为'符号不是连接的有效输出类型。
我确信这是我对宏如何工作的一些基本误解,并且有一种简单的方法可以做到这一点。我错过了什么?
答案 0 :(得分:6)
将它们连接成一个字符串,然后从该字符串创建一个符号。
(defmacro test (a b c)
(intern (concatenate 'string a b c)))
INTERN
会在当前包中实习该字符串,您也可以使用MAKE-SYMBOL
创建一个未加工的符号。
答案 1 :(得分:5)
对宏及其实现的困惑
我确信这是我对宏工作方式的一些基本误解
是:
宏和创建'词'是完全独立的,正交的概念。
Lisp中不存在'word'的概念。但是有符号,字符串,数字......
如果您考虑APPLEBANANACUBA
,那么您可能意味着符号。
解决问题
如果要创建符号串联的新符号,则需要:
内爆手术
让我们将此操作称为 implode ,这是它的历史名称:
(defun implode-symbols (symbols &optional (package *package*))
(when symbols
(values
(intern (with-output-to-string (stream)
(dolist (symbol symbols)
(write-string (symbol-name symbol) stream)))
package))))
CL-USER 30 > (implode-symbols '(a - b - c - foo - bar))
A-B-C-FOO-BAR
现在,可以制作一个更通用的版本,它可以内爆所有内容:
(defun implode (things)
(when things
(values
(intern (with-output-to-string (stream)
(dolist (thing things)
(princ thing stream)))))))
CL-USER 31 > (implode '(a - b - c - foo :bar - 42 - "BAZ"))
A-B-C-FOOBAR-42-BAZ
包含一些参数的宏
鉴于我们是一个从事物列表中创建符号的函数,我们可以轻松编写宏:
CL-USER 37 > (defmacro test (a b c)
`',(implode (list a b c)))
TEST
CL-USER 38 > (macroexpand-1 '(test foo bar baz))
(QUOTE FOOBARBAZ)
T
CL-USER 39 > (test foo bar baz)
FOOBARBAZ
原子,爆炸和爆炸
符号是原子。这意味着它们不是缺陷单元,它是链表的基本构建块。
你可以爆炸和内爆原子,这里是一个符号。
FOO
和BAR
- > FOOBAR
FOOBAR
- > F
,O
,O
,B
,A
,R