使用Clojure deftype作为参数化函数

Mat*_*att 7 clojure deftype

我试图在编译器中使用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提示.我如何获得这些提示?

Mic*_*zyk 7

你需要改变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 xdirect读取作为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期望一个字段名称的矢量,但显然列表也是如此......矢量仍然更加惯用.)