我正试图在编译器中使用clojure,因此需要参数化对deftype的调用;然而,我很难将类型提示传递下去。考虑以下代码:
(defn describe [x]
(let [fields (.getDeclaredFields x)
names (map #(.getName %) fields)
types (map #(.getType %) fields)]
(interleave types names)))
(defn direct [] (deftype direct-type [^int x]))
(defn indirect-helper [] (list ^int (symbol "x")))
(defn indirect [] (eval `(deftype ~(symbol "indirect-type") ~(indirect-helper))))以及来自REPL的以下会话:
Clojure 1.2.0-master-SNAPSHOT
1:1 user=> #<Namespace dataclass>
1:2 dataclass=> (direct)
dataclass.direct-type
1:3 dataclass=> (indirect)
dataclass.indirect-type
1:4 dataclass=> (describe direct-type)
(int "x")
1:5 dataclass=> (describe indirect-type)
(java.lang.Object "x")注意,为indirect-type生成的类丢失了direct-type所具有的^int提示。我怎样才能得到这些提示呢?
发布于 2010-07-26 07:32:32
您需要将indirect-helper更改为read
(defn indirect-helper [] [(with-meta (symbol "x") {:tag 'int})])原因是^int解析为^,然后解析为int;在Clojure1.2中,^引入了读者元数据(在1.1中,您将使用#^,它仍然有效,但在1.2中已弃用)。因此,direct中的^int x被读入为一个clojure.lang.Symbol,它的名称是"x",其元数据映射是{:tag int} (这里的int本身是一个符号)。(在本例中,符号的最后一个组件--它的名称空间--是nil。)
在来自问题文本的indirect-helper版本中,^int被附加到(symbol "x") --由符号symbol和字符串"x"组成的列表(特别意味着(list ^int (symbol "x"))的计算结果是一个包含1个元素的列表)。一旦评估了(symbol "x"),这个“类型提示”就会丢失。要解决这些问题,需要某种方法将元数据附加到由(symbol "x")生成的实际符号。
现在,在这种情况下,符号是在运行时生成的,所以您不能使用读取器元数据将类型提示附加到它。进入with-meta,它在运行时附加元数据(出于与此处相同的原因,在编写宏时经常使用它),这样就节省了时间:
user> (indirect)
user.indirect-type
user> (describe indirect-type)
(int "x")(顺便说一句,我以为deftype需要一个字段名称的向量,但显然列表也可以……向量当然更符合习惯。)
https://stackoverflow.com/questions/3330666
复制相似问题