2013-02-22 42 views
5

我有一个Java类Vector2,我想说服Clojure阅读器“很好地玩”。通过Clojure打印机和阅读器往返Java类

(def a (vec2 1 2)) 
(print-str a) 
=> "#<Vector2 [1 2]>" 

理想我想这个类中,可以通过Clojure的阅读器读取的形式打印出来。即我想以下返回true:

(= a (read-string (print-str a))) 

什么是实现这种往返能力的最佳方式?

+0

你不想涉及'EvalReader',我想? – 2013-02-22 10:56:50

+0

@Marko:对建议持开放态度。它并不专门用于外部API--更多的是为了方便REPL和轻松的序列化/反序列化。 – mikera 2013-02-22 11:01:32

+0

我认为'read-eval'左为真,读者将知道如何处理'#=(Vector2.1 2)'。 – 2013-02-22 11:48:09

回答

5

您需要为您的班级/类型提供print-dupprint-method multimethods。

退房core.clj

例:

(import 'java.util.Hashtable) 
(defmethod print-method Hashtable [x writer] 
     (binding [*out* writer] 
     (print (let [h (gensym)] 
       `(let [~h (Hashtable.)] 
        [email protected](map (fn [i] 
           `(.put ~h ~(str "\"" (.getKey i) "\"") ~(.getValue i) )) x) ~h))) )) 
(def a (Hashtable.)) 
(.put a "a" 1) 
(.put a "b" 2) 
(= a (eval (read-string (print-str a)))) 
+0

这似乎只包括写作结束。它如何阅读? – 2013-02-22 11:47:09

+0

'read-string'用于阅读。基本上这种multimethod会返回一个像'(vec2 1 2)'这样的字符串格式的s表达式,当执行时会导致创建所需的对象 – Ankur 2013-02-22 11:54:02

+0

这不是Mikera想要的:他不想将代码“他的对象;他想**阅读**,就像一个本地的Clojure矢量。 – 2013-02-22 12:30:02