Fork me on GitHub
#specter
<
2024-02-13
>
mlimotte23:02:21

Is it possible to compose replace-in with multi-transform? I couldn’t find anything in the docs about it, or through a Google search. I came up with this hack, based on the replace-in impl. But I’m pretty sure mutable-cell is not part of the public API, so this seems risky. I tested this and it seems to work, at least with small, simple data structure. But I’m not sure what mutable-cell does-- why not just use an Atom? Or is there another approach someone can suggest?

(defn mk-transformer-with-state
  [state transform-fn & {:keys [merge-fn] :or {merge-fn concat}}]
  (fn [& args]
    (let [res (apply transform-fn args)]
      (if res
        (let [[ret user-ret] res]
          (->> user-ret
               (merge-fn (spimpl/get-cell state))
               (spimpl/set-cell! state))
          ret)
        (last args)))))

(defn replace-in-with-multi-transform
  "How do we combine replace-in with a multi-transform?"
  []
  (let [state (spimpl/mutable-cell nil)]
    [(sp/multi-transform [sp/ALL :a sp/ALL :b
                          (sp/multi-path
                           [#(= % 5)
                            (sp/terminal
                             (mk-transformer-with-state state (fn [x] [(dec x) [x]])))]
                           [#(= % 3)
                            (sp/terminal
                             (mk-transformer-with-state state (fn [x] [(inc x) [x]])))]
                           )]
                         sample1)
     (spimpl/get-cell state)]))