specter

Latest version: 1.1.3
nathanmarz 2018-02-14T00:17:39.000243Z

@johanatan of course, navigators are infinitely composable

nathanmarz 2018-02-14T00:18:11.000255Z

will be easier to show you the most elegant approach if you give an example of the input and desired output

cperrone 2018-02-14T12:46:09.000227Z

Hi @nathanmarz and all, I’m beginning to use Specter everywhere 🙂. I’m still struggling with some admittedly basic recursion/tree transformation though. For example, here’s my input:

(def tree [0
                 [1]
                 [2 [3]]])
The tree is arbitrarily nested, each node is a vector of type
[root & children]
(e.g. [0] is the tree root, [1] and [2] its immediate children, [1] and [2] are siblings). My goal is to transform the tree into the following structure. In other words, each node under the root becomes an :li item. Also if a node has children, I’d like to “wrap” them with a :ul container. It should be simple, but I can’t get my head around it yet. But maybe you can help me on this one?
[:ul
       [:li {:id "1"}]
       [:li {:id "2"}
        [:ul
         [:li {:id "3"}]]]]

nathanmarz 2018-02-14T14:13:49.000521Z

@cperrone here's one way to do it:

(def tree [0
            [1]
            [2 [3]]])

(def NODE-CHILDREN
  (path INDEXED-VALS #(not= 0 (first %)) LAST))

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

(defn wrap [children id _]
  (if (empty? children)
    [:li {:id id}]
    [:li {:id id} (setval BEFORE-ELEM :ul children)]
    )
  )

(nth
  (transform
    [NODES
     (collect NODE-CHILDREN)
     (collect-one FIRST)
     ]
    wrap
    tree
    )
  2)

cperrone 2018-02-14T14:42:45.000100Z

ah brilliant, thank you @nathanmarz. I much appreciate it. I suspected I needed to collect values along the way, but I wasn’t sure how (I need to play more with that). Great answer. Would this be more typical of a zipper use, by the way? At some stage I wondered if walking with

(defn my-zipper [v]
  (z/zipper next rest my-make-node v))
(obviously then wrapped by the specter zipper :D) would have been easier for this case.

nathanmarz 2018-02-14T15:22:07.000466Z

@cperrone zippers aren't needed in this case

nathanmarz 2018-02-14T15:22:37.000438Z

it's best to avoid using zippers since they add a lot of overhead

👍 2
cperrone 2018-02-14T15:24:29.000029Z

I’m still studying your approach to the problem, in particular, I was surprised by the setval within the transform fn

nathanmarz 2018-02-14T15:27:26.000359Z

your use case does two things: wrap in :li and wrap in :ul

nathanmarz 2018-02-14T15:27:56.000896Z

the inner setval prepends to a vector without changing the type (as cons would do)

cperrone 2018-02-14T15:30:16.000470Z

yes. I guess I also need to check the result of the overall transform “before” you take the nth index.

nathanmarz 2018-02-14T15:31:09.000431Z

yea, the handling of the root is special with how you laid out the problem

cperrone 2018-02-14T15:33:56.000452Z

yes, maybe some slight tweaking on the input could help (as it’s often the case)

nathanmarz 2018-02-14T15:34:53.000582Z

if you have the control, then making the structure of the data as consistent as possible helps a lot

cperrone 2018-02-14T15:35:34.000146Z

eh eh I do. I though I was consistent though. [root children children] all the way no?

nathanmarz 2018-02-14T15:36:05.000512Z

yea, in this case it's the output that's slightly inconsistent

cperrone 2018-02-14T15:36:23.000301Z

true, the wrapping is slightly tricky

cperrone 2018-02-14T15:38:03.000138Z

i read somewhere that zippers are pretty lightweight by the way… I don’t particularly like the imperative navigation that it often leads to though.

nathanmarz 2018-02-14T15:39:34.000545Z

"lightweight" is relative

nathanmarz 2018-02-14T15:40:00.000764Z

compared to a straight reduce it's not

nathanmarz 2018-02-14T15:40:22.000626Z

it's not just performance, they also add conceptual overhead

1
cperrone 2018-02-14T15:40:23.000039Z

ah ah I guess so, especially in clojurescript, everything counts, so it’s a matter of tradeoffs

cperrone 2018-02-14T15:40:32.000051Z

indeed