Fork me on GitHub

had an issue where a cider-nrepl user made a custom IDeref type. printing would force a deref which would block the repl indefinitely. cider-nrepl added a bit on top but it seems that clojure itself does this on all IDeref's unless they are specifically marked IPending and aren't realized yet. This surprised me and I went looking to see if this was written down anywhere as a pretty decent gotcha. Is there an authoritative place that has this documented or is this just a wisdom you need to have?

Yehonathan Sharvit06:06:22

A question about clojure.walk usage for functions that transform map entries. Is it better to provide to clojure.walk/postwalk a function that handles maps or map entries? For instance, clojure.walk/keywordize-keys provide a function that handle maps:

(defn keywordize-keys
  "Recursively transforms all map keys from strings to keywords."
  {:added "1.1"}
  (let [f (fn [[k v]] (if (string? k) [(keyword k) v] [k v]))]
    ;; only apply to maps
    (postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m)))
Another option would be to write a function that handle map entries
(defn my-keywordize-keys
  "Recursively transforms all map keys from strings to keywords."
  {:added "1.1"}
  (let [f (fn [[k v]] (if (string? k) [(keyword k) v] [k v]))]
    ;; only apply to maps
    (postwalk (fn [x] (if (map-entry? x) (f x) x)) m)))

Yehonathan Sharvit06:06:41

To me the second option seems better as it relies on postwalk to build the map from the transformed entries

Yehonathan Sharvit06:06:06

Also, there is an in clojure.walk when the form has metadata. keywordize-keys suffer from the bug. while my-keywordize-keys doesn’t

Yehonathan Sharvit06:06:53

What do you guys think ? cc: @borkdude @alexmiller (mentioned in the bug)

👍 4
Ben Sless15:06:25

I'd rather not pass at all through map entries when possible and process maps with reduce-kv


I think the root cause should be solved which is clojure.walk. Then pick the most optimized solution built on that for keywordize-keys

Yehonathan Sharvit15:06:47

Assuming the bug in clojure.walk is fixed, what is the most optimized option for keywordize-keys?

Yehonathan Sharvit15:06:23

@UK0810AQ2 reduce-kv is not recusive

Ben Sless15:06:43

Neither is f in keywordize-keys. You can call it in a recursive fashion or recur from inside it

Ben Sless15:06:14

nor is the function passed to postwalk

Ben Sless15:06:32

It is my understanding that the most optimized option for the map? branch will be reduce-kv, more than into + xf. For anything faster than that you'll have to reimplement postwalk

Ben Sless15:06:14

If you have a guarantee the input is maps all the way down, you can forgo into completely in favor of reduce with recursive calls


> what is the most optimized option for keywordize-keys? benchmark

Ben Sless16:06:20

Assuming the input is only nested maps:

(defn foo
   (fn [m k v]
     (assoc m (if (string? k) (keyword k) k) (if (map? v) (foo v) v)))

(def m {"a" {"b" 1} "c" 2})

 (keywordize-keys m))
;; Execution time mean : 4.788510 µs

 (foo m))
;; Execution time mean : 332.201889 ns

Ben Sless16:06:59

For larger maps I'd reduce over transient maps

Yehonathan Sharvit07:06:12

@borkdude beside performance, what code is more elegant/idiomatic ?

Emmy Almaraz07:06:37

Hi y'all, I've spent two days on this error that I get when I run lein install. I'm trying to install the twtttr dependency. I'm unsure where it comes from since I'm using the standard reagent-project boilerplate and have not introduced much code. Linking my GitHub repo for context

Syntax error macroexpanding at (handler.clj:1:1).
Execution error (FileNotFoundException) at mute-twitter.handler/loading (handler.clj:1).
Could not locate mute_twitter/middleware__init.class, mute_twitter/middleware.clj or mute_twitter/middleware.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.

Full report at:
Compilation failed: Subprocess failed (exit code: 1)


@U013AK7J8MA what do you mean by "I'm trying to install the twttr dependency"? How do you do that?


Also looking at it seems there's no such depedency in the standard reagent template. Did you add it manually to your project.clj?


If you do lein install in your root project folder then the question is why would you need that....


@U013AK7J8MA I don’t see a mute-twitter.middleware namespace in your project. I think the message is unrelated to the dependency you’re trying to introduce.


Ah, I see. Carry on.

Emmy Almaraz17:06:17

Hi Jumar, the dependency is [twttr "3.2.3"] and installed it under dependencies in project.clj

Emmy Almaraz17:06:43

I'm not sure what the error message is trying to tell me since I haven't modified any code relating to the error message


I’d try it with an empty project skeleton first with no modifications. But better question is: why do you try to run lein install in the first place?

Emmy Almaraz17:06:20

How do I install the twttr dependency?

Emmy Almaraz17:06:28

This is how I've done it in the past


Hi, The book: 'Web Development with Clojure, Third Edition' is currently in beta and set to launch their final version on July'20 -which is next month. Will they increase or decrease the books pricing ($25.95 currently) when they launch? Or, Is it a good idea to wait for the launch?

Janne Sauvala09:06:17

Hi, the author @U050CBXUZ (or one of the two) replied to a comment in Reddit a few days ago saying that the release might take a couple of more months (;utm_medium=web2x)


Thanks for the info!


yeah, unfortunately fell a bit behind on the book with all the craziness 🙂

Romit Gandhi14:06:15

Currently whenever I add new query in queries.sql , I have to close and reopen REPL everytime to test it. I have also tried to reload in the REPL using (use '[demo.db.core :as db] :reload-all) but it didn't work. Currently I'm using Calva plugin in VS Code. So is there any way to test it without closing and reopening REPL everytime ?


Can you give some more context? Is this a public demo project?

Romit Gandhi16:06:41

@U0ETXRFEW, It's a private project and I'm using luminus framework. In the queries.sql all the queries are there, but when I do some modification in the file though I reload the db.core file it isn't reflected. So, I have to reopen the REPL for it. That's the main issue.

Romit Gandhi16:06:12

@U015E25EW80, I didn't understand perfectly, means what should I have to do?


@U012V3C1TPF Please don't cross-post the same question to both #clojure and #beginners

Drew Verlee19:06:28


[{:a [1 2]} {:a [3 4]} {:a [5 6 1]} ] 
I want to expand anytime the :a collection contains 1 or 2 such that their in their own collection e.g
[[1] [2] [3 4] [5 6] [1]]
I ended up writing a reduce inside a reduce to do this. Is there a better way?


(into [] (comp (map :a) (mapcat #(partition-by #{1 2} %))) [{:a [1 2]} {:a [3 4]} {:a [5 6 1]}])

💯 8

Following the reduce rational

 (fn [acc v] (into acc (partition-by #{1 2} (:a v))))
 [{:a [1 2]} {:a [3 4]} {:a [5 6 1]} ])


(let [as (mapcat :a coll)]
  (vec (partition-by #{1 2} as)))


@U3JH98J4R This version would put (3 4 5 6) in the same collection


ah, yeah you are right


which may be ok


You could write a function that takes a vector, and a collection of the values that you want to be in their own collection, e.g. #{1 2}, and return a collection of the vectors you want.


Once that is written and working as you like, it seems simple to call that inside of a reduce expression that does not contain a nested reduce , but does contain at least one call to that new function.


(def d [{:a [1 2]} {:a [3 4]} {:a [5 6 1]} ])

(letfn [(my-coll [coll] )]
  (fn [acc v] (my-coll (:a v)))
I was on my way @andy.fingerhut lol


this smells like mapcat


I solved it with mapcat in the thread =\

👍 6
🚀 3

Is there a general way to build a transducer pipeline for achieving the following if the functions fn-1, fn-2 and fn-3 are transducers? (map fn-3 (map fn-2 seq-2) (map fn-1 seq-1)) and have something like (sequence pipleline-fn seq-1 seq-2)


Juxt and comp


(comp fn-3 (juxt fn-2 fn-1) vector)


I have 2 different source seqs though. fn-1 applied on seq-1 and fn-2 applied on seq-2


The vector at the front gets mapped over pairing elements up


Then juxt applies the fns to each element in the pair


Then fn-3 gets the whole pair (which is why it may need a partial apply)


Sorry, I do not follow. Would you be able to show via example?

(sequence (map vector)
          (sequence (map keyword) ["a" "b" "c"])
          (sequence (map inc) [1 2 3]))


On my phone, it would be something like (sequence (map (comp ...)) s1 s2)


Ok, thanks. Will play around with that idea


Maybe partial apply fn-3