Fork me on GitHub
#specter
<
2018-01-24
>
dadair21:01:17

Given add-ref and parse-tree in the following snippet, is there a way to combine this pair of transform/traverse into a single traversal (to improve performance by not requiring a multi-pass of a large datastructure?)

(def NODE
    (sp/recursive-path [] p
                       (sp/continue-then-stay
                        (sp/must :children)
                        sp/MAP-VALS
                        p)))

  (def terminal2
    (sp/richnav [afn]
                (sp/select* [this vals structure next-fn]
                            (throw (Exception. "'terminal2' should only be used in multi-transform")))
                (sp/transform* [this vals structure next-fn]
                               (afn vals structure))))

  (def nodes-with-refs
    (sp/recursive-path [] p
                       (sp/continue-then-stay
                        (sp/putval :children)
                        (sp/must :children)
                        sp/ALL
                        (sp/collect-one sp/FIRST)
                        sp/LAST
                        p)))

  (defn add-ref [root]
    (sp/multi-transform
     [(sp/putval :root)
      :root
      nodes-with-refs
      :ref
      (terminal2 (fn [vals _] (ref/unparse vals)))]
     root))

  (defn parse-tree [root]
    (reduce
     (fn [result item]
       (if-let [parsed (parse-node item)]
         (conj result parsed)
         result))
     []
     (sp/traverse [:root :children MAP-VALS NODE] root)))

  (->> test-segment ;; potentially large datastructure with form {:root {:name "root" .. :children {..}}}
       add-ref ;; add path down the tree to each node in the tree, e.g., "/a/b/c" where A, B, C are nodes with names a, b, c
       parse-tree)

nathanmarz21:01:13

@dadair can you just collect the path in parse-tree?

nathanmarz21:01:02

besides that, the latest release adds vtransform which eliminate the need for you to do multi-transform with custom terminal2

nathanmarz21:01:17

you might benefit here from a new vselect which navigates to [collected-vals navigated-value]

dadair22:01:38

Thanks for pointing out vtransform, cleans up the code! I’m not quite sure how I would go about collecting the path in parse-tree, and passing those collected values into the reducing function.

dadair22:01:02

hmm, are you suggesting that I could change the sp/traverse call to a vselect, and then item in the reduce would be [collected navigated]?