【发布时间】:2018-08-31 08:25:34
【问题描述】:
我用defmacro 包装defrecord,因为我想要一种特定类型的具体地图在中心位置注册自己(用于serde)。
宏是:
(defmacro def-thing! [name [& fields] & opts+specs]
`(let [klass# (defrecord ~name ~fields ~@opts+specs)
map-constructor-fn# (resolve (symbol (str 'map-> ~name)))]
; use the map-constructor-fn#
))
问题在于 let 表单根据之前是否已经调用过宏(比如我在 nrepl 中重新加载命名空间源文件时)以不同的方式进行宏扩展。
第一次,name 是一个符号。
第二次,name 是一个 Java 类。
当然,我可以测试name~ 是否是Java 类,然后调用.getSimpleName() 并做相应的事情。
但是 Clojure 的核心贡献者一定遇到过这种情况?这是如何处理的?为什么我没有在 Clojure 核心源代码中看到 defrecord 或 emit-defrecord 的明确解决方案?我错过了什么?
【问题讨论】:
-
不完全相关,只是为了澄清一下,参数列表不应该是
[name fields & opts+specs]吗?还是您的调用语法与defrecord不同? -
我从
defrecord签名中获取的[& fields]表格。解构本质上是强制fields成为seq而不执行:pre形式的简写。我想。