am looking for a CLJC suite of ordered collections but it seems like https://github.com/clj-commons/ordered is just for the JVM. Is that right? Do any of the crew know of a CLJS equivalent (cos my search fu is letting me down today ! )
there is cljs implementation for ordered-map
yes, ha ... just noticed that and mentioned it in the channel
So you are looking for the ordered set?
You can also solve this by keeping a vector and set around with the same data.
(defn record-state-change
"Add updated-item to the current state under the change-id key.
If the change-id does not exist, add it to a FIFO list of changes."
[{:keys [changelog] :as state} updated-item change-id]
(cond-> state
(not (get state change-id)) (assoc state :changelog
(vec (conj changelog change-id)))
:always (assoc change-id updated-item)))I could drop the cond-> if I had an ordered set cos the assoc is always idempotent
So yeah, you can code around it but just would be nice
A small price to pay for not using another dependency I'd say
yes, that is a very decent opinion
Maybe I am more optimistic about the quality of libs from the Clojure community than I am about JS but still, fewer deps are better indeed
Instead of (cond-> state ...) I'd write here
(cond-> (assoc change-id updated-item) (not (get state change-id)) ...)@raymcdermott but wait, how is your example an ordered set? It's an ordered map, essentially?
the map is unordered, as usual but the changelog list is ordered by insertion and avoids duplicate insertion.
if you assoc first you cannot test for key existence
So you have to update items, but you want to keep the order of first insertion
yes
How big are these items? How many elements?
Another way to do this is to have an extra key: inserted-at ... with some timestamp or incrementing value so you can sort the map entries based on that
the change-id is of the form id/digest and the digest is based on some input text. If that changes we will get a new digest and a new compound ID
(ns replacement.protocol.state
(:require [replacement.protocol.hashing :as hashing]
#?(:cljs [promesa.core :as p])))
(defn record-state-change
"Add updated-item to the current state under the change-id key.
If the change-id does not exist, add it to a LIFO list of changes."
[{:keys [changelog] :as state} updated-item change-id]
(cond-> state
(not (get state change-id)) (assoc :changelog (vec (cons change-id changelog)))
:always (assoc change-id updated-item)))
(defn update-state
[state updated-item distinction-key form-id]
(let [digest-input (get updated-item distinction-key)]
#?(:clj (let [digest (hashing/digest digest-input)]
(record-state-change state updated-item (keyword form-id digest)))
:cljs (p/let [digest (hashing/digest digest-input)]
(record-state-change state updated-item (keyword form-id digest))))))How often do you need to know the order?
always ... you want to track history properly
I mean, how often do you want to query the order
oh and I know I should be using a database for this 🙂
yes, that too ;)
I'll get there
In this stage I'd just use the extra key on the map to keep the insert order around
I don't know how often the order will be queried ... maybe never but at least once when I demo it 😉
unless performance becomes an issue, but you haven't proven that to yourself yet
Are you also preparing your ClojureD workshop now? ;)
🤫
the thing I'm trying to leverage is that s/conform will produce data that only changes if there is a meangingful change in the code text. Then I can keep a history of those changes and perform structural diffs.
I'm not getting into all the edge cases around that but I think it will be interesting to see how far we can go with that data
btw. for LIFO I usually use seq + conj for insertions + peek/pop for takes. That way allows you to not convert data from seq to vector and back on each insertion
noted
FYI this is how I'm currently calling it (update-state state var-data :conformed form-id)
It's not terribly elegant but for the moment at least, it works
actually, there is a map.cljs but not a set.cljs which, of course, is what I am looking for.