Fork me on GitHub
#clojure
<
2020-06-09
>
dpsutton04:06:46

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"}
  [m]
  (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"}
  [m]
  (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 https://clojure.atlassian.net/browse/CLJ-2568 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

borkdude15:06:14

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

borkdude15:06:58

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

Ben Sless16:06:20

Assuming the input is only nested maps:

(defn foo
  [m]
  (reduce-kv
   (fn [m k v]
     (assoc m (if (string? k) (keyword k) k) (if (map? v) (foo v) v)))
   {}
   m))

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

(cc/quick-bench
 (keywordize-keys m))
;; Execution time mean : 4.788510 µs

(cc/quick-bench
 (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 https://github.com/ealmz/mute-twitter

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:
/var/folders/25/6gbmvthj0n3fgp5_tr3m8w2m0000gn/T/clojure-9163810633608100048.edn
Compilation failed: Subprocess failed (exit code: 1)

jumar07:06:25

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

jumar07:06:16

Also looking at https://github.com/reagent-project/reagent-template/blob/master/resources/leiningen/new/reagent/project.clj it seems there's no such depedency in the standard reagent template. Did you add it manually to your project.clj?

jumar07:06:07

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

jkrasnay11:06:04

@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.

jkrasnay11:06:23

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

jumar17:06:22

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

kosengan08:06:00

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 (https://www.reddit.com/r/Clojure/comments/gwc1hf/borrow_copy_of_web_development_with_clojure_third/fsuznhj?utm_source=share&amp;utm_medium=web2x)

kosengan09:06:51

Thanks for the info!

yogthos12:06:15

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 ?

pez15:06:41

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?

seancorfield17:06:47

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

Drew Verlee19:06:28

Given

[{: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?

Derek20:06:23

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

💯 8
bartuka20:06:43

Following the reduce rational

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

emccue21:06:40

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

Derek22:06:34

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

emccue22:06:10

ah, yeah you are right

Derek22:06:41

which may be ok

andy.fingerhut20:06:36

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.

andy.fingerhut20:06:13

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.

bartuka20:06:59

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

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

lilactown20:06:31

this smells like mapcat

Derek20:06:46

I solved it with mapcat in the thread =\

👍 6
🚀 3
Ari21:06:54

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)

hiredman22:06:28

Juxt and comp

hiredman22:06:53

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

Ari22:06:06

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

hiredman22:06:42

The vector at the front gets mapped over pairing elements up

hiredman22:06:02

Then juxt applies the fns to each element in the pair

hiredman22:06:35

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

Ari22:06:46

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]))

hiredman22:06:37

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

Ari22:06:22

Ok, thanks. Will play around with that idea

hiredman22:06:23

Maybe partial apply fn-3