我有一段代码来实现包含地图的原子地图的参考
> (def a (example.DynaRec.)
> (dosync (assoc! a 3 {:id 3 :contents "stuff"} 4 {:id 4}))
;;=> #[DynaRec@1a659078: {4 [<Atom@118eb00c: {:id 4}] 3 [Atom@242110fc: {:id 3 :contents "stuff"}]]
Run Code Online (Sandbox Code Playgroud)
我想改变它在repl中显示的方式,以便它只输出
> a
;;=> ({:id 3 :contents "stuff"}
;; {:id 4})
Run Code Online (Sandbox Code Playgroud)
如何才能做到这一点?代码如下所示:
(ns example.dyna-rec
(:gen-class
:name example.DynaRec
:prefix "-"
:init init
:state state
:extends clojure.lang.AFn
:implements [clojure.lang.IDeref
clojure.lang.Seqable
clojure.lang.ILookup
clojure.lang.ITransientMap]))
(defn- $ [this] (:data (.state this)))
(defn- valid?
([e]
(valid? e []))
([this e]
(every? #(contains? e %) (:required (.state this)))))
(defn -deref [this] @($ this))
(defn -valAt
([this k] ((-deref this) k nil))
([this k nv]
(if-let [vatom ((-deref this) k nv)]
@vatom)))
(defn -invoke
([this k] (-valAt this k))
([this k nv] -valAt this k nv))
(defn -seq [this] (seq (-deref this)))
(defn -count [this] (count (-deref this)))
(defn -without [this obj]
(alter ($ this) dissoc obj))
(defn -assoc
([this obj] (-assoc this (:id obj) obj))
([this k v]
{:pre [(valid? this v)
(= k (:id v))]}
(alter ($ this) assoc k (atom v))
this))
(defn -conj [this obj]
(-assoc this obj))
(defn -persistent [this]
(-deref this))
(defn -init []
[[] {:required #{:id}
:data (ref {})}])
要扩展经典的Java模型(clojure包含)你可以实现自己.toString生成正确的字符串,然后告诉REPL如何正确打印这个新类
首先toString在dyna-rec.clj中添加一个超级基本:
(defn- -toString [this]
(str (into {} this)))
Run Code Online (Sandbox Code Playgroud)
这可以像这样调用:
(defn- -toString [this]
(str (zipmap (keys this) (map deref (vals this)))))
example.DynaRec> (.toString a)
"{}"
example.DynaRec> (str a)
"{}"
Run Code Online (Sandbox Code Playgroud)
然后改进打印机以匹配您想要的输出:
(defn- -toString [this]
(str (zipmap (keys this) (map deref (vals this)))))
Run Code Online (Sandbox Code Playgroud)
并测试它:
example.DynaRec> (str a)
"{3 {:id 3, :contents \"stuff\"}, 4 {:id 4}}"
example.DynaRec>
Run Code Online (Sandbox Code Playgroud)
这仍然无法在REPL上正确打印,因此我们需要扩展打印机使用的多方法(print-method),REPL使用它来了解您的新类:
(defmethod print-method
example.DynaRec
[this, w]
(print-method (zipmap (keys this) (map deref (vals this))) w))
Run Code Online (Sandbox Code Playgroud)
这会产生你想要的东西:
example.DynaRec> a
{3 {:id 3, :contents "stuff"}, 4 {:id 4}}
Run Code Online (Sandbox Code Playgroud)