2014-10-04 54 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