Clojure defmacro 丢失元数据
我正在尝试创建一个带有类型提示的 def
sa String 的小 Clojure 宏:
(defmacro def-string [name value]
`(def ^String ~name ~value))
(def-string db-host-option "db-host")
当我宏扩展
它时,类型提示丢失了:
(macroexpand '(def-string db-host-option "db-host"))
;=> (def db-host-option "db-host")
别介意类型提示的智慧这。
为什么宏会丢失元数据?如何编写此宏或任何包含元数据的宏?
I am trying to create a little Clojure macro that def
s a String with a type hint:
(defmacro def-string [name value]
`(def ^String ~name ~value))
(def-string db-host-option "db-host")
When I macroexpand
it, the type hint is lost:
(macroexpand '(def-string db-host-option "db-host"))
;=> (def db-host-option "db-host")
Never mind the wisdom of type hinting this.
Why is the macro losing the metadata? How do I write this macro, or any that includes metadata?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
^
是一个读取器宏。 defmacro 永远看不到它。提示被放在列表(unquote name)
中。例如,将(meta ^String 'x)
与(meta ' ^String x)
进行比较以查看效果。您需要将提示放在符号上。
以及用法:
^
is a reader macro.defmacro
never gets to see it. The hint is put on the list(unquote name)
. Compare for example(meta ^String 'x)
with(meta ' ^String x)
to see the effect.You need to put the hint on the symbol.
And the usage:
元数据不会出现在宏展开中,因为它应该是“不可见的”。
如果宏正确(事实并非如此),您应该能够调用 (meta #'db-host-option) 来检查 var 上的元数据。
请注意, (def sym ...) 在从符号接收到的 var 上插入元数据。但是 ^Tag ~name 在 ~name (取消引用名称)上设置元数据,而不是在绑定到名称的传入符号上设置元数据。它不能做任何其他事情,因为 ^Tag ... 处理是由读取器完成的,一旦宏扩展开始,读取器就已经完成了。
你想要类似的东西
Metadata doesn't show up in a macroexpand since it's supposed to be "invisible".
If the macro is correct (which it isn't) you should be able to call (meta #'db-host-option) to inspect the meta data on the var.
Note that (def sym ...) inserts metadata on the var that it receives from the symbol. But ^Tag ~name sets the meta data on ~name (unquote name), not on the passed in symbol bound to name. It can't do anything else since ^Tag ... processing is done by the reader, which is already finished once macro expansion starts.
You want something like