This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
Let’s say that I have an atom containing a set, and I want to react to changes in that set. Is there a way to add a watch that only triggers if the contents of the atom were actually changed? Or will I have to perform a diff on every update the figure this out?
@henrik: in your watch handler use identical? to detect changes on interested paths in the atom, it is fast
I have just solved similar problem with reagent reactions in my project, I had thousands of watch handlers which became slow, solved it this way: https://github.com/darwin/plastic/blob/master/cljs/src/main/plastic/reagent/sonar.cljs#L29-L36
Instead of letting reagent register thousands of watch handler on atom, I register one watch handler, maintain a map of paths and when watch handler is triggered I go recursively from root and prune the tree with identical?, then call my real change handlers only if some paths I was interested in really changed
@darwin, awesome, thank you! I just realized I wrote something similar (yet different) over here, but I didn’t use identical?
. Would that improve the performance do you think? https://github.com/eneroth/plato/blob/master/src/plato/core.cljs#L13-L27
@henrik: identical? is just a pointer compare, you are doing deep walk and construction of difference, which is definitely slower
btw. I think you implemented a subset of https://clojuredocs.org/clojure.data/diff
@darwin, true, but the idea is to terminate when branches are identical, so it would make sense to use it I guess.
@darwin, yes, that was absolutely the idea (to implement an altered version of diff). Because of the way data is stored in local storage, it doesn’t make sense to look for diffs in vectors (since they are stored as strings anyway).
identical? may be tricky, depends how you update your atom, for me this discussion was helpful: https://github.com/reagent-project/reagent/pull/143
sometimes you can update atom with value which is equal to the old one, but not identical?
so maybe in case of shallow, small structures you actually want to be doing equality test instead of identical?
btw. you can look at my overwrite-map helper, which is paying for equality test only during write, if equal it does not break identity
https://github.com/darwin/plastic/blob/master/cljs/src/main/plastic/util/helpers.cljs#L99-L136
Hm, I guess that given that identical?
returns false, one could check with =
, if the performance benefits of not re-rendering are greater than potentially checking the entire data structure. When identical?
returns true, the search tree will still be pruned.
@darwin, yep, this code:
(def test-atom (atom #{:one :two}))
(add-watch test-atom :test-watch #(when-not (identical? %3 %4)
(println "Old: " %3 " New: " %4)))
(swap! test-atom conj :one)
prints Old: #{:one :two} New: #{:one :two}
, just as you predicted263 p;[\kop41441plhn6y-----+9
@maxp: I would recommend using core.async
. But if that’s not available, you can always just use Java’s facilities directly.
This article has a section on using alts!
for timeouts: http://www.braveclojure.com/core-async/#4__Choice
If I have a map like this {:title "whatever" :group {:section1 {:tag1 "this" :tag2
Oops pressed send by accident
Trying again If I have a map like this: {:title " whatever " :group {:section1 {:t1 "a" :t2 "b"} :section2 {:t1 "c" :t2 "d"}} :footer "etc"} What is the best way to transform it to {:title " whatever " :section1 {:t1 "a" :t2 "b"} :section2 {:t1 "c" :t2 "d"} :footer "etc"} , stripping out the :group?
(merge (dissoc x :group) (:group x))
Oh perfect thanks!
When using defschema, how do you mark a field as optional?
s/maybe is for values. If you want a key in a map to be optional, there’s s/optional-key
In compojure-api, when defining the :body-params, how can I specify that some are optional?
I tried :body-params [x :- Long, y :- (s/maybe Long)] and :body-params [x :- Long, (s/optional-key y) :- Long] but neither worked.
@arohner: ah… no, that’s not what I want.
arohner: how would it look like if only x was required? {x :- Long}?
Isn’t that a hashmap with odd number of elements?
arohner: the vector doesn’t mean that the api will receive a vector, it’s the way parameters are described.
with {x Long} I get: java.lang.RuntimeException: Binding form is not vector: {x Long}, compiling:(routes/services.clj:20:1)
:body-params [{x :- Long nil}, {y :- Long nil}] might be a way, but it looks odd.
There’s no fn yet, I’m just building the playing with the API. I think you are thinking in terms of compojure, not compojure-api/swagger/schema