2

I've got a piece of code to implement a ref of a map of atoms containing maps

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

I want to make change the way this is displayed in the repl so that it only outputs

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

how can this be done? The code is shown below:

(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 {})}])
4

1 に答える 1

5

従来の Java モデル (clojure が採用) を拡張するに.toStringは、正しい文字列を生成する独自のモデルを実装してから、この新しいクラスを適切に出力する方法を REPL に指示します。

toStringdyna-rec.clj にスーパー ベーシックを追加することから始めます。

(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 で使用されるプリンター (print-method) で使用されるマルチメソッドを拡張する必要があります。

(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}}
于 2012-09-14T00:45:40.880 に答える