我试图在编译器中使用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))))
Run Code Online (Sandbox Code Playgroud)
以下来自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")
Run Code Online (Sandbox Code Playgroud)
请注意,为indirect-type生成的类已经丢失了direct-type所具有的^ int提示.我如何获得这些提示?
你需要改变indirect-helper阅读
(defn indirect-helper [] [(with-meta (symbol "x") {:tag 'int})])
Run Code Online (Sandbox Code Playgroud)
原因是^int解析^后面跟着int; ^,在Clojure 1.2中,介绍了读者元数据(在你使用的1.1中#^,它仍然有效,但在1.2中已弃用).因此,^int x在direct被读取作为clojure.lang.Symbol他的名字是"x"和其元数据映射是{:tag int}(与int正在此间本身的象征).(nil在这种情况下,符号的最后一个组成部分 - 它的命名空间.)
在indirect-helper来自问题文本的版本中^int附加到(symbol "x")- 包含符号symbol和字符串的列表"x"(特别是意味着(list ^int (symbol "x"))评估为1个元素的列表).(symbol "x")评估后,此"类型提示"将丢失.要解决问题,需要将元数据附加到生成的实际符号的某种方法(symbol "x").
现在在这种情况下,符号是在运行时生成的,因此您无法使用reader元数据将类型提示附加到它.Enter with-meta,在运行时附加元数据(并且在编写宏时经常用于与此处相同的原因)并保存日期:
user> (indirect)
user.indirect-type
user> (describe indirect-type)
(int "x")
Run Code Online (Sandbox Code Playgroud)
(顺便说一句,我认为deftype期望一个字段名称的矢量,但显然列表也是如此......矢量仍然更加惯用.)
| 归档时间: |
|
| 查看次数: |
480 次 |
| 最近记录: |