Created
March 1, 2017 22:21
-
-
Save ustun/648af2ed6053e2edd1611b8308e07ff8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Let's say we have a feed of questions and each question has an answer, and each answer has an id. | |
We want to find the answer with id=5 and update its like count. | |
Assume the data structure is nested, so | |
(def feed (atom {:questions [{:id 1 :answers [{:id 5, text: 'foo', :like-count 4}]}]}) | |
If I know that the answer I'm targeting is at 0th position of 0th question, I can do: | |
(swap! feed update-in [:questions 0 :answers 0 :like-count] inc) | |
But I don't actually know that it is at 0th position. I only know the answer id. What do I do then? | |
If it were mutable, it would be easy, since my "answer view" would actually hold on to the answer map. So, | |
I could just do (swap! my-answer update :like-count inc) | |
But it is not. One could use cursors for that, but will I create new cursors for each answer? | |
So, imagine the following: | |
(swap! feed update-in [:questions ALL :answers #(= :id 5) :like-count] inc) | |
Here, update took a path where we checked an arbitary predicate. | |
I run into this all the time in UI. Of course, if the data was modelled "normalized" or as in Datomic, so that my structure was like the following, I could just easily find and swap the answer. | |
(def feed (atom | |
{:question-ids ["q1" "q2"] | |
:q1 {:text "Question 1" :answer-ids ["a1" "a5"]} | |
:a5 {:text "Answer 5" :like-count 5}})) | |
Here, I can directly find a5. | |
(swap! feed update-in [:a5 :like-count] inc) | |
But now, my views need to do the denormalization. So whenever I display question 1 and its answers, I need to do a "db" lookup. | |
Yes, at the very least, we need something in core like update-when that takes a list of predicates.
For reference, here is the version with specter:
(transform [:questions ALL #(= (:id %) 1) :answers ALL #(= (:id %) 2) :like-count] inc feed)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think the last line reads pretty nice.
update-when
could be more general by replacing equality with a more general predicate.