Fork me on GitHub

What’s the best lenses library for clj & cljs?


I think Lentes is the one most folks go to @aaron51 but I've never used it.

👍 4

(my feeling is they're not used much in Clojure because we tend to work with get-in, assoc-in, and update-in instead?)


lenses get a lot more useful when you have complex types for your lookups, and we don't really run into that with clojure - some more advanced lens features might be better emulated by specter


@noisesmith thanks, specter is what I was looking for! Not sure how that differs from lenses, yet


Nested #() function is not allowed, how to change the nested #() code?


@stardiviner pull the second one out to a named function. The threading macro does not play nice with anonymous functions (it threads via code transformations, not via result passing)


You can bind it to a name inside a let or letfn if you don’t want to expose it outside of the outer function


@dadair I use #(->> % :prelude first (format "....")) now. Seems works fine. I though must be function style in threading-macro.


Ah right, I didn’t look at the contents of the anonymous function. Yes in this case you don’t need to wrap the format call into a function as the prior “result” will already be passed as the last argument to the format call.


@stardiviner Or use (->> (format "\n#+begin_quote\n%s\n#+end_quote\n")


I find it's really nice to start with (-> ...) and drop (->> ...) in as needed.


(and, yes, in your case you can just use ->> because everything except format only takes one argument so the first argument is also the last argument)


@seancorfield you mean (-> % :prelude first (->> (format "...")) ) ?


Right, perfectly fit


Jesus christ using clj-http and cheshire with some simple map commands is just blowing my mind


how the hell did I use to work with json before


Like a child eating sand

rainbow-mouth 8

i think clj-http used cheshire under the hood so you can just supply json-parsing as an option to clj-http


Yeah it's an optional dependency


@emilaasa I know the feeling 😂


I mean it's just unfair what I've been doing before


So parsing json by hand? 😄


Hi guys, so I have a snippet here, I was trying to hydrate a collection of objects concurrently using core.async, but it keeps freezing whenever I run it


Basically what I was aiming is I want to create a channel for each hydration process, run it, and retrieve it using map since I need the order of the objects to remain intact.


I also observe that the repl process didn't use any network connection at all, using nettop


pmap had done the trick for me, I just want to explore core.async at this point


Hi @henrik, thank you, you've been very helpful ever since I raise my questions about this yesterday. I notice that the main difference from your solution is that the go-blocks that does the "task" receives its arguments from a go channel, whereas mine from outside the go-blocks scope. Is that problematic? I thought that the value from outside the blocks will be retained because of closure.


@hawari.rahman17 Not really, a go-block will return immediately, but process whatever’s inside synchronously, and then return the results on a channel.


It can totally be done in that way as well.


So in your solution, you could skip the channel and just put a bunch of goblocks on a seq, then <!! over them.


@hawari.rahman17 This is a go-only version of your code above.


Ah shoot, I think I know what my problem was, I wasn't doing recur properly: returning the rest of the objects on what should be the next object


Yeah, that would be it 🙂


My mistake, I tend to forgot things like this


Which is what you actually asked, wasn’t it 😁


Yeah, you’ve got to carry the collection along to the next loop.


Many thanks @henrik, what I thought was a core.async related problem turns out to be a basic clojure problem, haha


Glad that I posted it in #beginners


But yeah, as you can see, you can make do with a simple go in some cases. Channels are useful when you want to hand off the stream of results to something else, like a separate handler.


Also, since putting something on a channel (without buffer) that already has something in it will block until something else removes that thing from the channel, you can have two (or more) asynchronous processes running in lock-step with each other.


The producer will wait until the consumer has taken the thing from the channel. It comes in handy at times.


I don't know why but it seems by using core.async in my use case quite improved my throughput compared to my previous solution with pmap


That’s interesting. Are you constraining the number of simultaneous processes with core.async?


Or are the same number of processes being run in parallel for both solutions?


It's the same, I gathered benchmark using time


Hang on, I think pmap uses real threads. By default, core.async would use lightweight threads.


Usually it takes about 1 secs to complete the whole process, now it's just about 600 msecs


So the difference could be the overhead of creating and tearing down threads.


That's what I thought as well, but I don't imagine the improvement will be this dramatic 😁


Time to refactor some old code then, I'd happily change one letter to this if that's what it takes for efficiency

👍 4

Thanks again @henrik, it's been quite a revelation.


Glad to help 🙂

Alex Miller (Clojure team)14:09:01

core.async’s lightweight threads are of course multiplexed over a pool of actual threads

👍 4

Yes, of course! (I had no idea)

Alex Miller (Clojure team)14:09:03

if you’re using pmap, and your process is taking 1 minute to exit, you might want to check that you are calling (shutdown-agents) at the end

Denis G17:09:41

hey guys, what does this mean (apply * 3 [1 2 3])

Denis G17:09:44

evaluates to 18

Denis G17:09:48

is step function just +


(* 3 1 2 3)


No worries! 🙂

Denis G17:09:19

partition function is too slow for my needs (Doing a challenge on hackerrank in Clojure :P) How else would I be able to read data in a sliding window manner, like (parition k 1 coll) but without partition. By using for?


are you sure the partition is the slow part?


@denisgrebennicov do you need an output collection? if no, doseq will be faster than for

Denis G17:09:05

my procedure was doing something like this

(->> arr
         (partition k 1)
         (map (fn [coll] [(- (apply max coll) (apply min coll))]))
         (apply min)))

Denis G17:09:25

therefore I am guessing that the partition part is the bottleneck. Assumption, but still

Denis G18:09:31

Thinking of doing for with subvec in :let clause


flatten is likely the biggest perf hit there, it's an ugly function


Not going to save you much, but mapcat would work here instead of flatten.

👍 4
Denis G18:09:23

just not used to mapcat yet. Great point


you don't need the max and min traversals since you've already sorted it right?

👍 4
Denis G18:09:20

still timeout. Now it's like this

Denis G18:09:22

(defn maxMin [k arr]
    (let [sorted-arr (vec (sort arr))]
        (->> (for [i (range (- (count arr) k))
                   :let [coll (subvec sorted-arr i (+ i k))]]
                 (- (apply max coll) (apply min coll)))
             (apply min))))


min and max are first and last respectively

👍 4
Denis G18:09:09

😄 sorry guys 😄


what's the problem that you are solving


what's the biggest smallest difference between k values?

Denis G18:09:19

find the subarray with min fairness

Denis G18:09:28

whereby fairness is max-min of the subarray

Denis G18:09:43

What is the most idiomatic way to access nth element of the seq, list, vector

Denis G18:09:56

there are nth, get, and something else ?

Denis G18:09:23

The solution which doesn't timeout is this

(defn maxMin [k arr]
    (let [sorted-arr (vec (sort arr))]
        (->> (for [i (range (- (inc (count arr)) k))
                   :let [coll (subvec sorted-arr i (+ i k))]]
                 (- (nth coll (dec k)) (nth coll 0)))
             (apply min))))

Denis G18:09:17

subvec is O(1) therefore the solution should be good 😉


did it work?

Denis G18:09:31

yeap. Thanks

Denis G18:09:49

Still, the question about: > What is the most idiomatic way to access nth element of the seq, list, vector > there are nth, get, and something else ?

Denis G18:09:10

seq, list, vec is a function itself?

Denis G18:09:19

@hiredman exception is preferred instead of nil?

Denis G18:09:26

in case of out of bounds


hard to say, I think in general when I write programs that pull data out by index, I always get the index from the data, so it is never out of bounds


and I much prefer associative data like maps to indexed, so the usage of nth is pretty minimal

Denis G18:09:26

how one would write (min-by fn coll) function

Denis G18:09:59

sort-by then first? 😄


user=> (doc min-key)
([k x] [k x y] [k x y & more])
  Returns the x for which (k x), a number, is least.

  If there are multiple such xs, the last one is returned.

👍 4

Should one use Clojure with the JDK by Oracle or the Open JDK?


@tobias.vetter they are discussing that in #clojure right now. I use open on my laptop

👍 8

That can be slightly simplified to (map-indexed vector "abacbdcd")

Denis G19:09:38

thanks 😅 just figured it out right now 😄 Looks so clean 🙂


(println "Hello Clojurians")


Welcome! Always glad to see new folks trying out Clojure!


I like how on error it shows my actually input, and on success it shows the reader-expansion

Denis G21:09:14

how can I find min lexicographic string in the seq

Denis G21:09:42

was thinking of (min-key (partial compare "") s)

Denis G21:09:48

but compare doesn't work in this case

Denis G21:09:13

(compare "a" "") = 1 (compare "x" "") = 1


why are you comparing them to empty strings


(sort ["bob" "apple"])

Denis G21:09:30

sort is O(nlong), min is O(n)

Denis G21:09:58

want to generate some kind of value for string

Denis G21:09:03

and by this value find the min


(map compare ["a" "b" "c"] ["c" "b" "a"]) => (-2 0 2)

Denis G21:09:39

but if I have like ["word1" "word2" "word3"]

Denis G21:09:47

how should I proceed without sorting


(reduce (fn [x y]
          (if (neg? (compare x y)) x y))
        ["cat" "bob" "apple"])


walk down and compare them and pass on the one that compared "less than"


earlier i was just showing you were always comparing against the empty string, not between two values

Denis G21:09:20

damn. You are right, thanks! Was thinking of writing my own cost function, like this

(defn str-cost 
  (->> str
       (map-indexed (fn [idx val] (* (Math/pow 32 idx) (int val))))
       (reduce +)))


or sort backwards: (fn [x y] (compare y x))


(just jumping in... #no-context)

Denis G21:09:58

But reduce with compare sounds very good. Thanks!


You could also copy and paste the implementation of min-key, and change all < to corresponding calls to compare. min-key was written with numeric comparison in mind, not more general comparison.