我有以下宏:
(defmacro my-macro [k]
`(do
(def pair
[
k
~(symbol (str "-" (name k)))]
)))
...扩展为:
(macroexpand-1 `(my-macro :n/k))
(do (def user/pair [user/k -k]))
...相反,我希望它扩展到
(do (def user/pair [:n/k -k]))
如何让宏保留关键字及其命名空间?
谢谢!
答案 0 :(得分:1)
有两件事让你的问题有些混乱。我早些时候误解了它。
'
和macroexpand-1
,而不是背景`。反向标记通常仅用于宏定义中,以描绘一段"模板代码"。k
,您在示例中使用的关键字是:n/k
。这些重复的名称会引起混淆。让我们重申一下问题:
(ns clj.demo)
(defmacro my-macro [arg]
`(do
(def pair
[
arg
~(symbol (str "-" (name arg)))]
)))
(println (macroexpand-1 `(my-macro :n/k)))
;=> (do (def clj.demo/pair [clj.demo/arg -k]))
因此,我们位于clj.demo
命名空间中,该命名空间将应用于符号pair
和arg
。我们需要使用arg
替换参数~
:
(ns clj.demo)
(defmacro my-macro [arg]
`(do
(def pair
[
~arg
~(symbol (str "-" (name arg)))]
)))
(println (macroexpand-1 '(my-macro :n/k)))
;=> (do (def clj.demo/pair [:n/k -k]))
这就是你想要的。
答案 1 :(得分:1)
您可以使用namespace
和name
功能从传入的关键字中提取所需的部分,并根据需要进行组合:
user> (defmacro my-macro [k]
`(do
(def pair
[~(keyword (str (namespace k) "/" (name k)))
~(symbol (str "-" (name k)))])))
#'user/my-macro
user> (macroexpand-1 `(my-macro :n/k))
(do (def user/pair [:n/k -k]))
答案 2 :(得分:1)
您需要使用k
从语法引用中转义~k
:
(defmacro my-macro [k]
`(def ~'pair [~k ~(symbol (str "-" (name k)))]))
我在这里也做了一些其他的改变:
(
或[
放在一行的末尾 - 并将)
和]
与他们关闭的表达式放在同一行。do
在这里完全是多余的。如果您希望宏扩展为(def pair ...)
,则需要
~
)quote
符号pair
(即'pair
)将这些放在一起,你有~'pair
。你必须这样做的原因是,在Clojure中,`<symbol>
被读作(quote <current-namespace>/foo>)
,其中<current-namespace>
代表当前的命名空间。但是def
不会使用命名空间的名称。因此~'
舞蹈。
(但你可能想要在pair
上进行参数设置...否则,每个命名空间多次使用my-macro
并不是很有用。)
总的来说,这似乎是一个非常奇怪的宏。我不知道你想要完成什么,但我可能采取不同的方法。