2014-10-04 58 views
2

我試圖在clojurescript中構建出一個由原子支持的concept of a Cursor。遊標是一種遞歸拉鍊機制,用於編輯不可變的嵌套關聯數據結構。Clojure新手與協議奮鬥

我在Clojure很新手,你能幫我發現我的錯誤嗎?

(defprotocol Cursor 
    (refine [this path]) 
    (set [this value]) 
    (value [this])) 

(defn- build-cursor* [state-atom paths] 
    (reify Cursor 
    (set [this value] (swap! state-atom (assoc-in @state-atom paths value))) 
    (refine [this path] (build-cursor* state-atom (conj paths path))) 
    (value [this] (get-in @state-atom paths)))) 

(defn build-cursor [state-atom] 
    (build-cursor* state-atom [])) 

(comment 
    (def s (atom {:a 42})) 
    (def c (build-cursor s)) 
    (assert (= (value c) {:a 42})) 
    (set c {:a 43}) ;; WARNING: Wrong number of args (2) passed to quiescent-json-editor.core/set at line 1 <cljs repl> 
    (assert (= (value c) {:a 43})) 
    (def ca (refine c :a)) ;; WARNING: Wrong number of args (2) passed to quiescent-json-editor.core/refine at line 1 <cljs repl> 

    (assert (= (value ca) 43)) 
    (set ca 44) 
    (assert (= (value ca) 43)) 


) 

回答

1

我也是Clojure的新手,但是我刺了一刀,發現了兩個問題。

首先,set方法與核心庫函數衝突(即使它在Cursor協議中)。爲了調試起見,我添加了下劃線前綴以避免這種情況。

其次,似乎在根光標上調用_set會破壞該值。我發現,assoc-in不處理空路徑[]你所期望的方式:

(assoc-in {} [] {:a 7}) 
; {nil {:a 7}} 

......所以這是在_setcond的原因。

這裏是我的測試代碼:

(ns cursory) 

(defprotocol Cursor 
    (_path [this]) 
    (_root [this]) 
    (_refine [this path]) 
    (_set [this value]) 
    (_value [this])) 

(defn- build-cursor* [state-atom paths] 
    (reify Cursor 
    (_path [this] paths) 
    (_root [this] @state-atom) 
    (_set [this value] (cond 
         (empty? paths) (reset! state-atom value) 
         :else (assoc-in @state-atom paths value))) 
    (_refine [this path] (build-cursor* state-atom (conj paths path))) 
    (_value [this] (get-in @state-atom paths)))) 

(defn build-cursor [state-atom] 
    (build-cursor* state-atom [])) 

(comment 
    (def s (atom {:a 42, :b 84})) 
    (def c (build-cursor s)) 
    (_set c {:a 44, :b 88}) 
    (_root c) 
    (_path c) 
    (_value c) 
    (def ca (_refine c :a)) 
    (_path ca) 
    (_value ca) 
    (_set ca 42) 
    (get-in {:a 1 :b 2} []) 
    (assoc-in {} [:a :b] 7) 
    (assoc-in {} [] {:a 7}) 
    (empty? []) 
) 
+0

JIRA問題的assoc命令,在與空路徑:http://dev.clojure.org/jira/browse/CLJ-1520 – lnmx 2014-10-06 17:02:05