Fork me on GitHub
Tema Nomad07:01:01

what is the standard solution to render clojure API json response with ring? ring-json lib?


That's what I have seen used in many places

👍 2
Patrick Winter08:01:30

I've the following dependency graph:

(def dependency-graph  {:n3 #{:n1 :n2}
                        :n4 #{:n3}})
Each element in the set is a direct dependency of a node (the map key). How would I invert this data structure in a functional way so it describes the required-by relationship instead of the depends-on relationship? I've tried something like this, but I would need to additionally merge all the maps at each reduce step:
(reduce {} (fn [inverted [node dependencies]]
             (for [dep dependencies]
               (if (contains? inverted dep)
                 (let [required-by (get inverted dep)]
                   (assoc inverted dep (conj required-by node)))
                 (assoc inverted dep #{node})))) graph)
Is there an elegant solution to this?


 (fn [acc par deps]
   (reduce #(update %1 %2 (fnil conj #{}) par) acc deps))


(fixed a typo)

Patrick Winter11:01:07

This looks a lot cleaner 🙂. Thanks @U04HK53G7SQ


No worries!


(def x {:foo 1, :bar -3}) (def y {:foo 1, :bar -3})   (identical? x y) returns false

(def a 1)
(def b 1)

Why (identical? a b) - returns true ?


Because the maps are not identical objects in memory. Check out and read the comments, especially the last one about being careful about using the function at all


It's JVM semantics, you can come up with much simpler cases, like (identical? 0.0 .0.0) => false


It's best considered a useless function


Oh ok Thanks you


I have seen code in the clojure core that make use with-meta when do we need to use with-meta in our application ?


when you have to add metadata to some dynamically created object that supports metadata.

user=> (meta (let [x [1 2 3]] ^:foo x))
user=> (meta (let [x [1 2 3]] (with-meta x {:foo true})))
{:foo true}
the first line here might look like you add metadata to the object but in fact it adds metadata to the var #'x that doe not exists outside of let expression


Why do we have to add metadata ?


I meant, which scenario we add it? is there any drawback if we do not add it ?


there are few cases when it can be usefull here is one for example


by adding metadata you can implement a protocol implicitly


Will take a look


Metadata is also useful for cases where you want to be able to compare data using = while attaching certain metadata to the data, e.g. :source . The data stays equivalent, but you get to keep track of where it came from.


This returns true, for example:

(= (with-meta {:a 1} {:source "$some_user"})
   (with-meta {:a 1} {:source "$some_other_user"}))


Can I ask for some advice please, as I've hit a brick wall in my understanding? I'm sure this has been asked before but I can't find an answer that I fully understand. I have an array of maps that is originally derived from a json file. I'm trying to perform a substring search on one of the keys in each map and create a new array of maps with all the full map entries that return true. e.g [{:title "the quick brown fox" :data "data" :more "data"} {:title "the slow brown fox" :data "data2" :more "data2"} ] (into [] (filter (string/includes? (:title map) "quick") data) would return [{:title "the quick brown fox" :data "data" :more "data"}] However, after a mixed bag of various attempts at using filter I either get empty arrays, arrays with true or false values or errors. Are there any useful links or documentation that might point me in the right direction? Thanks!


I'm not sure if it's a typo or part of your problem, but you're not passing a function to filter, you're passing the boolean result of calling a function


vs. say (filter (fn [{title :title}] (str/includes? title "quick")) data)


Yes, sorry it's become peudo code at this point after a few goes around,🙃

R.A. Porter16:01:43

If you care about the result being a vector and not a lazy seq, you could call

(let [foo [{:title "the quick brown fox"
            :data  "data"
            :more  "data"}
           {:title "the slow brown fox"
            :data  "data2"
            :more  "data2"}]]
  (filterv #(str/includes? (:title %) "quick") foo))
Just filter would return a lazy seq.


that code is testing the maps for string inclusion

R.A. Porter16:01:20

Edited. I’d elided the extraction of the :title.


@U2EJEK2SX if you want to paste a gist or something I can try to help


A way to think about this so you can get yourself unstuck in the future. When you want to do something to a collection, write a function that works on a single one. And only once that function is working on a single one then use it with filter and the rest of the functions

☝️ 4
🙂 2

Thanks everyone, I got into the weeds with trying to parse every map etc


Meta-tip: I know well the temptation, but I try never to post anything other than actual code. People are going to spend time on analyzing and even running it, I figure, so it has to be real. No harm I guess in loudly announcing the code is just pseudo-code up front. hth!


Sorry! I'll keep that in mind in the future

🙏 2

Demonstration of @U11BV7MTK’s suggestion. Break it down to extremely easy problems, and build back up to the target.

👍 3

Thanks @U90R0EPHA that's a really helpful example


I could do with some help, I have the following data structure

(let [c {1 [1 2 3 4 5]
         2 [1 2 3 4 5]
         3 [6 7 8 9 10]
         4 [1 4 5 6 7]}]
And values a and b. What I'd like to do is remove all keys from c that are less than a , and when the key is equal to a, remove all values from that key which are less than b. e.g.
(let [c {1 [1 2 3 4 5]
         2 [1 2 3 4 5]
         3 [6 7 8 9 10]
         4 [1 4 5 6 7]}
      a 3
      b 7]
Would give
{3 [7 8 9 10]
 4 [1 4 5 6 7]}
What I've tried to get working:
(-> (into {} (remove (fn [[k _]] (< k a)) c))
    (assoc a (remove (fn [[_ v]] (< v b))(c a))))
But I'm getting the error ; TypeError: n.replace is not a function and no idea why!


This works, but I'm thinking there must be a nicer way

(into {} (for [[k v] c
                 :when (>= k a)]
             [k (if (= k a)
                  (remove (fn [x] (< x b)) v) v)]))


I hadn't! Would that make removing keys less than n simpler ?


`(subseq (into (sorted-map) {1 [1 2 3 4 5] 2 [1 2 3 4 5] 3 [6 7 8 9 10] 4 [1 4 5 6 7]}) < n)`


nice, i didnt' know about subseq either


❯ clj -Sdeps '{:deps {org.clojure/data.avl {:mvn/version "0.1.0"}}}'
Downloading: org/clojure/data.avl/0.1.0/data.avl-0.1.0.pom from central
Downloading: org/clojure/data.avl/0.1.0/data.avl-0.1.0.jar from central
Clojure 1.11.1
user=> (require '[ :as avl])
user=>   (let [c (avl/sorted-map
            1 [1 2 3 4 5]
            2 [1 2 3 4 5]
            3 [6 7 8 9 10]
            4 [1 4 5 6 7])
        a 3
        b 7]
    (avl/subrange c >= a <= b))
{3 [6 7 8 9 10], 4 [1 4 5 6 7]}


Is their any specific reason why I was getting the error n.replace is not a function with my code ? I'm finding clojure(script) errors pretty tricky to deal with and find the actual problem


for the rest i'd go w/ something like (as-> thing m (into (sorted-map) m) (update m a (partial filter (partial >= b)) (subseq m < n) (into {} m)) or whatever


avl trees offer a non-linear way to accomplish this. just wanted to highlight that. ie no filter on the keys yourself

👍 2

I'll check it out, wasn't aware of that library


on the error, you're trying to destructure members of (c a) into [_ v], but it's a flat vector


oh yeah! I was confused thinking I was still dealing with key value pairs at that point.


obviously the error message is of no help


I don’t think it’s great, but an option is reduce-kv with a cond in the body

Michał Frątczak20:01:35

How is it possible this works? pluss function arity is 2

(defn pluss [x y]
    (Integer/sum x y))
  (reduce pluss [1]) => 1

Alex Miller (Clojure team)20:01:59

"If coll has only 1 item, it is returned and f is not called."