This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-08-27
Channels
- # admin-announcements (1)
- # announcements (11)
- # babashka (17)
- # beginners (26)
- # calva (6)
- # cider (2)
- # circleci (1)
- # clojure (41)
- # clojure-dev (1)
- # clojure-europe (31)
- # clojure-france (2)
- # clojure-italy (10)
- # clojure-nl (7)
- # clojure-norway (5)
- # clojure-spec (15)
- # clojure-uk (42)
- # clojurescript (4)
- # code-reviews (12)
- # conjure (10)
- # datalog (2)
- # datascript (15)
- # datomic (37)
- # emacs (1)
- # events (5)
- # fulcro (19)
- # jobs (1)
- # jobs-discuss (9)
- # kaocha (2)
- # luminus (14)
- # meander (4)
- # membrane (39)
- # off-topic (26)
- # other-languages (2)
- # re-frame (13)
- # reitit (6)
- # rewrite-clj (39)
- # sci (6)
- # shadow-cljs (33)
- # test-check (15)
- # vrac (17)
- # xtdb (7)
@deactivateduser10790 thank you for sharing your process!
@smith.adriane No worries, Aero is just a detail we can ignore that for now.
The general question is: is there a downside to adding the root of ones project to the classpath? I have everything working, but i’m just curious at this point :thinking_face:
The driver of the question: io/resource
would need the root of the project that in order to find a file at the root.
@tkjone my only thought would be whether having two roots that overlap (`.` and ./src
) might cause issues. I don’t think I’ve ever dug into what the Java classloader(s) do in that case, let alone the Clojure classloader(s).
It’s certainly not done much in Java (or, I suspect, Clojure), so I would be a bit hesitant to do it, albeit without any specific objections to cite…
Good point and yeah it’s not something I’ve see either.
I have a pattern of many functions like this where the first two args are always the same spec, but the third argument varies (always a seq of at least two items, the first always being a keyword). Thus, it's the very last item in my spec ::proj
where the variation will happen. Can s/cat be composed in a way that I can DRY this up?
no? I don't see any R to D
Another spec question: I was hoping (s/spec? ::my-spec)
would work, but I see there is also get-spec
. Is there anything that combines the two (returns true if the argument is either a spec or keyword for a spec in the registry)?
most other calls in the library can take a spec-or-kw param. I just thought spec? would do the same.
Don’t think so
I want to implement a CRDT in Clojure, specifically a LWW Element-Set (which is more like a hashmap). I'd like to have core functions like merge
work on it, but conj
would need to take a time that the k/v is true as-of.
Does anyone have some advice?
I’ve thought about this a bit. I think you could handle this using a dynamic var & binding
if they need to be run in some kind of context i'd probably eschew the standard abstractions
@lilactown that was my goto as well, although dynamic vars are always suspect for this kind of thing. They're noticeably missing from any core data structures for example.
I suppose you could get a new data structure by doing (merge (updating-to my-crdt (now)) {:foo "bar"})
. There's a risk of someone accidentally reusing an old time they didn't intend I suppose.
dynamic variables have tradeoffs. there are performance & complexity implications that can detract from it.
the benefit is that you can easily reuse core fns, and also provide runtime verification. e.g. you can throw if it’s not inside an as-of
One problem with building on core is that you might violate expectations:
(defn foo [doc a]
(let [x (merge doc a)]
(is (true? (= (get x :a) (get a :a))))))
Can't think of much which would do that, but still.clojure.core/merge is about merging values, merging crdts is about merging the casual history of the crdts and constructing a new value that is the result of the merged history
It's very convenient to have access to the wide array of key renames and such that we have access to via clojure core though.
There's only a handful of functions which modify a map and then read it back with assumptions it can read it's changes.
there are operations on the point in time value of the crdt, and there are operations on the casual history, I think you can potentially use the clojure.core functions for operations on the current value, with the implicit time of now, and then another set of functions for operating on the history
so clojure.core/merge of crdt1 and crdt2 would act like merging maps, ignoring the history that crdt2 might have a history of some keys from crdt1 being deleted
and you would have a crdt/merge (I've used join as a name for this in the past) that would merge crdts respecting history
it seems like what you really want is to be able to easily go to and from a hash map and a CRDT
(-> crdt
(as-of (now)) ;; returns a map
(merge {:foo-bar}) ;; returns a map
(->> (crdt/update crdt (now))) ;; returns the new crdt with the new value updated as of time `(now)
`
you could also do what hiredman said and create a new crdt2 out of the newly created map and join
themI'm possibly looking at something closer to an ORDT it seems. I can prune history pretty aggressively. I'm not looking much at the causal history. All operations are about adding information and only having it update if it's newer than what is already there.
I don't think I've seen crdt datastructures that aren't last write wins, the way they are categorized is how concurrent operations are resolved (add wins, remove wins etc)
At least some CRDTs designed for collaborative text editing can have more elaborate conflict resolution strategies. Martin Kleppmann has an interesting talk on the subject at https://martin.kleppmann.com/2020/07/06/crdt-hard-parts-hydra.html. Of course that's a bit of a different use case than a generic hash map.