2014-10-04 2 views
2

Я пытаюсь построить concept of a Cursor в clojurescript, поддерживаемый атомом. Курсор представляет собой рекурсивный механизм застежки-молнии для редактирования неизменяемой вложенной связанной структуры данных.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}} 

... так что причина cond в _set.

Вот мой тестовый код:

(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 вопрос для ассоциативного в с пустым путем: http://dev.clojure.org/jira/browse/CLJ-1520 – lnmx

Смежные вопросы