Q:

Clojure - using specter to transform a nested data structure, replacing one node with several

I'm using specter to transform nested data structures in Clojure, but I haven't got the hang of it yet.  In particular, I'm trying to create a transformation that will find an item - at any depth - that matches a predicate, and replace it will several items. 
[:top
 [:arbitrary 1 2
  [:nesting
   2
   3
   [:needle] ; <-- the thing to find
   ]]]

-->

[:top
 [:arbitrary 1 2
  [:nesting
   2
   3
   [:n1] [:n2] [:n3]  ; <-- 3 items inserted in the place of 1
   ]]]

What I can't figure out is how to splice the replacement items into the parent vector, i.e., how to replace one item with three items, and not with one item containing three children. 

A:

I don't know how to do this using Specter, but here's a function to do it with clojure.zip:
(defn splice-replace [zipper smap]
  (loop [loc zipper]
    (if (z/end?  loc)
      (z/root loc)
      (recur
       (z/next
        (if-let [sub (smap (z/node loc))]
          (reduce (comp z/right z/insert-right)
                  (z/replace loc (first sub))
                  (rest sub))
          loc))))))

You can call it with a zipper of your data structure and a map from values you want to replace to a sequence of their replacement values to be spliced into their position:
(def zipper
  (z/vector-zip [:top
                 [:arbitrary 1 2
                  [:nesting 2 3 [:needle]]]]))

(splice-replace zipper {[:needle] [[:n1] [:n2] [:n3]]})
 => [:top [:arbitrary 1 2 [:nesting 2 3 [:n1] [:n2] [:n3]]]]

(splice-replace zipper {[:nesting 2 3 [:needle]] (range 3 10)})
=> [:top [:arbitrary 1 2 3 4 5 6 7 8 9]]

A:

(defn replace-needle [input replacement]
    (let [needle-parent?      #(= % [:needle])
          NEEDLE-PARENT      (recursive-path
                                 [] p (cond-path
                                          #(and (vector? %) ( some needle-parent? %)) [( continue-then-stay [ALL p])]
                                          vector? [ ALL p]))
          inject-replacement (fn inject [x] (vec (mapcat #(if (needle-parent? %)  replacement [%]) x)))]
        (transform [NEEDLE-PARENT] inject-replacement input)))

(let [input       [:top
                   [:arbitrary 1 2
                    [:nesting 2 3 [:needle]]]]
      replacement [[:n1] [:n2] [:n3]]]
    (replace-needle input replacement))

