specter

Latest version: 1.1.3
2018-05-10T06:24:21.000005Z

I'm having trouble figuring out how to navigate to an entry that could have a variable number of steps. An individual navigate/transform is easy enough and looks something like this:

(sp/transform [(node-named "2002") :children (node-named "01") :expanded] invert test-tree)
However I need to be able to provide a path that could have from 1 to 4 entries. In the above example it would be ["2002" "01"]. What would be the best way to approach this? I tried building the navigator with for in a let statement like this:
(defn toggle [tree path]
  (let [nav (conj
              (vec
                (interpose :children (for [p path] (conj (seq [p]) 'node-named ))))
              :expanded)]
    (sp/transform nav invert tree)))
But although this gives me a value for nav that looks exactly right, running it throws Not a navigator errors

schmee 2018-05-10T08:01:32.000207Z

try something like this:

(defn navigator [strs]
  (path (mapcat (fn [s] [:children ALL #(= (:name %) s)]) strs)))

schmee 2018-05-10T08:07:00.000140Z

also, the invert function can be replaced with the core function not 🙂

1
2018-05-10T08:39:02.000143Z

@schmee That looks promising, thanks. I'm getting the right node back now. Just got to massage it a bit to toggle :expanded. Which I will do with not😳

schmee 2018-05-10T08:39:52.000246Z

remember that you can compose paths with a simple vector:

(transform [(navigator ["2000" "01"]) :expanded] not test-tree)

2018-05-10T08:50:17.000005Z

yup, got it working now. Still waiting for the ah-ha moment with specter, but it is doing some useful things even though often I'm not entirely sure why....

schmee 2018-05-10T09:37:10.000077Z

stick with it! 🙂 like anything worth learning it takes practice but the payoff is worth it IMO

schmee 2018-05-10T09:37:22.000354Z

you can always ask here if you get stuck 👍

😁 1
2018-05-10T06:26:47.000072Z

where node-named invert and test-tree are:

(defn node-named [n]
  (sp/walker #(= (:name %) n)))

(defn invert [b]
  (if b false true))

(def test-tree
  {:name "root"
   :focus ["root"]
   :expanded true
   :children [{:name "2000"
               :expanded true
               :children [{:name "01"
                           :expanded true
                           :children [{:name "project-1"}
                                      {:name "project-2"}]}
                          {:name "02"
                           :expanded true
                           :children [{:name "project-5"}
                                      {:name "project-6"}]}]}
              {:name "2002"
               :expanded false
               :children [{:name "01"
                           :expanded false
                           :children []}]}]})