Clojure 如何使gen类对象显示得更好
我有一段代码来实现一个包含映射的原子映射的refClojure 如何使gen类对象显示得更好,clojure,Clojure,我有一段代码来实现一个包含映射的原子映射的ref > (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"}]] 如何做到这一点?代码如下所示: (ns
> (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"}]]
如何做到这一点?代码如下所示:
(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 {})}])
(ns示例。dyna-rec)
(:gen类
:name example.DynaRec
:前缀“-”
:init init
:州
:扩展clojure.lang.AFn
:实现[clojure.lang.IDeref
clojure.lang.sekable
clojure.lang.ILookup
clojure.lang.ITransientMap]))
(defn-$[this](:数据(.state this)))
(defn-有效吗?
([e]
(有效?e[]))
([e]
(每个?#(包含?e%)(:必需(.state this(())))
(defn-deref[this]@($this))
(defn-valAt)
([k](-deref this)k nil))
([本k nv]
(如果让[vatom((-deref this)k nv)]
@vatom)
(defn-调用
([this k](-valAt this k))
([这个k nv]-这个k nv的值)
(定义-序号[本](序号(-deref this)))
(defn-count[this](count(-deref this)))
(定义-无[本obj]
(更改($this)dissoc obj))
(defn-协会
([this obj](-assoc this(:id obj)obj))
([本k v]
{:pre[(有效?本v)
(=k(:id v))]}
(更改($本)助理k(原子五))
这个)
(defn-conj[本obj]
(-assoc this obj))
(defn-持久性[此]
(-deref this))
(defn-init[]
[[]{:required}{:id}
:data(ref{}}])
要扩展经典的java模型(clojure支持),您可以实现自己的
.toString
,它生成正确的字符串,然后告诉REPL如何正确打印这个新类
首先,向dyna-rec.clj添加一个超级基本的toString
:
(defn- -toString [this]
(str (into {} this)))
这可以这样称呼:
(defn- -toString [this]
(str (zipmap (keys this) (map deref (vals this)))))
example.DynaRec> (.toString a)
"{}"
example.DynaRec> (str a)
"{}"
然后改进打印机以匹配所需的输出:
(defn- -toString [this]
(str (zipmap (keys this) (map deref (vals this)))))
并测试它:
example.DynaRec> (str a)
"{3 {:id 3, :contents \"stuff\"}, 4 {:id 4}}"
example.DynaRec>
这仍然无法在REPL上正确打印,因此我们需要扩展REPL使用的打印机使用的多方法(打印方法),以了解您的新类:
(defmethod print-method
example.DynaRec
[this, w]
(print-method (zipmap (keys this) (map deref (vals this))) w))
这会产生你想要的:
example.DynaRec> a
{3 {:id 3, :contents "stuff"}, 4 {:id 4}}
example.DynaRec> a
{3 {:id 3, :contents "stuff"}, 4 {:id 4}}