【问题标题】:Using Clojure deftype as a parameterized function使用 Clojure deftype 作为参数化函数
【发布时间】:2010-07-25 19:22:01
【问题描述】:

我正在尝试在编译器中使用 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")

请注意,为间接类型生成的类丢失了直接类型所具有的 ^int 提示。如何让这些提示贯彻执行?

【问题讨论】:

    标签: clojure deftype


    【解决方案1】:

    您需要更改 indirect-helper 才能阅读

    (defn indirect-helper [] [(with-meta (symbol "x") {:tag 'int})])
    

    原因是^int解析为^后跟int^,在 Clojure 1.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 需要一个字段名称的向量,但显然列表也可以工作......向量当然更惯用。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多