Fork me on GitHub
#specter
<
2018-06-25
>
nathanmarz11:06:27

@pepe looks like

(use 'com.rpl.specter)

(def data
  [{:id 0}
   {:id 1}
   {:id 2 :parent-id 1 :val 1}
   {:id 3 :parent-id 1 :val 1}
   {:id 4 :parent-id 2 :val 2}
   {:id 5 :parent-id 3 :val 2}
   {:id 6 :parent-id 3 :val 2}
   {:id 7 :parent-id 0 :val 100}
   {:id 8 :parent-id 7 :val 200}
   {:id 9 :parent-id 6 :val 3}])

(defn- node-index [graph id]
  (select-first
    [INDEXED-VALS
     (selected? LAST :id (pred= id))
     FIRST]
    graph
    ))

(defnav to-node [id]
  (select* [this graph next-fn]
    (if-let [i (node-index graph id)]
      (next-fn [graph i])
      NONE
      ))
  (transform* [this graph next-fn]
    (if-let [i (node-index graph id)]
      (first (next-fn [graph i]))
      graph
      )))

(defn- child-indices [graph id]
  (select
    [INDEXED-VALS
     (selected? LAST :parent-id (pred= id))
     FIRST]
    graph
    ))

(defnav CHILDREN []
  (select* [this [graph i] next-fn]
    (let [id (-> graph (nth i) :id)
          child-i (child-indices graph id)]
      (if (empty? child-i)
        NONE
        (doseq [i child-i]
          (next-fn [graph i])
          ))))
  (transform* [this [graph i] next-fn]
    (let [id (-> graph (nth i) :id)
          child-i (child-indices graph id)]
      (if (empty? child-i)
        [graph i]
        [(reduce
          (fn [graph ci] (first (next-fn [graph ci])))
          graph
          child-i
          )
         i]
         ))))

(defnav NODE []
  (select* [this [graph i] next-fn]
    (next-fn (nth graph i))
    )
  (transform* [this [graph i] next-fn]
    [(transform (nthpath i) next-fn graph) i]
    ))

(def DESCENDANTS (recursive-path [] p (stay-then-continue CHILDREN p)))

4
pepe12:06:30

@U173SEFUN thank you very much for your time. I can't imagine coming with something like this myself. I will report back, how it works for me.

pepe11:06:11

I got to try it today and it again gives me Maximum call stack exceeded on around 1000 nodes. It seems I have to go recursive 🙂. Still thank you very much, I have learned a lot from your code!

firstclassfunc13:06:54

Morning. I am trying to convert the hiccup output from instaparse into an associative structure. Is specter a good solution for converting

[:entity
 ([:name "J"]
  [:locations
   ([:address [:slot "slot0"] [:port "1"]]
    [:address [:slot "slot1"] [:port "2"]]
    [:address [:slot "slot2"] [:port "3"]]
    [:address [:slot "slot3"] [:port "4"]]
    [:address [:slot "slot4"] [:port "5"]]
    [:address [:slot "slot5"] [:port "6"]])])]
into
{:entity 
   [{:name "J"}
    {:locations 
     [{:address {:slot "slot0" :port "1"}} 
      {:address {:slot "slot1" :port "2"}}
      {:address {:slot "slot2" :port "3"}}
      {:address {:slot "slot3" :port "4"}}
      {:address {:slot "slot4" :port "5"}}
      {:address {:slot "slot5" :port "6"}}]}]}
?

nathanmarz13:06:32

@firstclassfunc is the transformation vector -> map and list -> vector for all reachable vectors and lists?

nathanmarz13:06:12

oh it's a little more complicated

nathanmarz13:06:47

since the :slot and :port vectors get combined into a single map

firstclassfunc13:06:06

ok well it can be done in multiple steps..

nathanmarz13:06:28

but the general structure is

(def NODES
  (recursive-path [] p
    (if-path coll?
      (continue-then-stay ALL p)
      )))

(multi-transform
  [NODES
   (if-path vector?
     (terminal vec->map)
     (terminal vec)
     )]
  data
  )

nathanmarz13:06:36

you fill in the vec->map function

firstclassfunc13:06:50

ah cool. Thanks so much (y)