Hi @nathanmarz I have a type that implements PersistentVector protocols (basically acts like a vector) and today we found a bug:
(sp/setval [sp/FIRST] {:x 3} (obj [{:x 2}])) => ({:x 3})
sp/FIRST returned a list and not a vector.
we did a little digging and found that in UpdateExtremes:
(extend-protocol UpdateExtremes
#?(:clj clojure.lang.IPersistentVector :cljs cljs.core/PersistentVector)
(update-first [v afn]
(update-first-vector v afn))
(update-last [v afn]
(update-last-vector v afn))
...
#?(:clj Object :cljs default)
(update-first [l val]
(update-first-list l val))
(update-last [l val]
(update-last-list l val)))
it doesn't recognize my type as vector so it defaults to list impl.
I extended the protocol to support my type:
(extend-protocol
UpdateExtremes
VectorObjWrapper
(update-first [v afn] (update-first-vector v afn))
(update-last [v afn] (update-last-vector v afn)))
but update-first-vector & update-last-vector are private so I ended up copying them:
(defn- update-first-vector [v afn]
(let [val (nth v 0)
newv (afn val)]
(if (identical? sp/NONE newv)
(subvec v 1)
(assoc v 0 newv))))
(defn- update-last-vector [v afn]
;; type-hinting vec-count to ^int caused weird errors with case
(let [c (int (vec-count v))]
(case c
1 (let [[e] v
newe (afn e)]
(if (identical? sp/NONE newe)
[]
[newe]))
2 (let [[e1 e2] v
newe (afn e2)]
(if (identical? sp/NONE newe)
[e1]
[e1 newe]))
(let [i (dec c)
newe (afn (nth v i))]
(if (identical? sp/NONE newe)
(pop v)
(assoc v i newe))))))
Is this the best way to go about it?
(I also have a Map type and I'm thinking about all the other protocols in specter that I should implement)hey @nathanmarz we are facing this issue again with a different protocol (i guess)
it's for a custom type of map that keypath doesn't add values for the path
can you point me to which protocol should we extend?
(sp/setval [:x :y] 12 (obj {})) => nilok nevermind, i have managed to figure out how to apply it
yea, you would need to extend the protocols the navigator uses to get the navigator working on different types
or you could make a new navigator