2

我有一段代码来实现包含映射的原子映射的引用

 > (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"}]]

我想改变它在 repl 中的显示方式,以便它只输出

> a 
;;=> ({:id 3 :contents "stuff"}
;;    {:id 4})

如何才能做到这一点?代码如下所示:

(ns example.dyna-rec
  (:gen-class
   :name example.DynaRec
   :字首 ”-”
   :init 初始化
   :state 状态
   : 扩展 clojure.lang.AFn
   :实现 [clojure.lang.IDeref
                clojure.lang.Seqable
                clojure.lang.ILookup
                clojure.lang.ITransientMap]))

(defn- $ [this] (:data (.state this)))

(定义-有效?
  ([e]
     (有效?e []))
  ([这个电子]
     (每个?#(包含?e %)(:必需(.state this)))))

(defn -deref [this] @($ this))

(定义-valAt
  ([this k] ((-deref this) k nil))
  ([这个k nv]
    (if-let [vatom ((-deref this) k nv)]
      @vatom)))

(定义-调用
  ([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 - 没有 [这个 obj]
  (alter ($ this) dissoc obj))

(定义-关联
  ([this obj] (-assoc this (:id obj) obj))
  ([这个千伏]
   {:pre [(有效?这个 v)
          (= k (:id v))]}
    (alter ($ this) assock (atom v))
    这))

(defn -conj [这个 obj]
  (-关联这个 obj))

(定义 - 持久 [this]
  (-deref 这个))

(定义-init []
  [[] {:必填 #{:id}
        :数据(参考{})}])
4

1 回答 1

5

要扩展经典的 java 模型(clojure 包含),您可以实现自己的.toString生成正确字符串的模型,然后告诉 REPL 如何正确打印这个新类

start by adding a super basic toString to dyna-rec.clj:

(defn- -toString [this]
  (str (into {} this)))

this can be called like this:

 (defn- -toString [this]
 (str (zipmap (keys this) (map deref (vals this)))))

example.DynaRec> (.toString a)
"{}"
example.DynaRec> (str a)
"{}"

then improve the printer to match your desired output:

(defn- -toString [this]
  (str (zipmap (keys this) (map deref (vals this)))))

and test it:

example.DynaRec> (str a)
"{3 {:id 3, :contents \"stuff\"}, 4 {:id 4}}"
example.DynaRec> 

This still does not print correctly at the REPL, so we need to extend the multimethod used by the printer (print-method) which is used by the REPL to know about your new class:

(defmethod print-method 
  example.DynaRec
  [this, w]
  (print-method (zipmap (keys this) (map deref (vals this))) w))

this produces what you seek:

example.DynaRec> a
{3 {:id 3, :contents "stuff"}, 4 {:id 4}}
于 2012-09-14T00:45:40.880 回答