Fork me on GitHub
#beginners
<
2018-09-07
>
aaron5101:09:48

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

seancorfield01:09:45

I think Lentes is the one most folks go to @aaron51 http://funcool.github.io/lentes/latest/#examples but I've never used it.

seancorfield01:09:05

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

noisesmith02:09:52

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

aaron5102:09:46

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

stardiviner02:09:44

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

dadair02:09:46

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

dadair02:09:13

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

stardiviner02:09:59

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

dadair02:09:44

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.

seancorfield02:09:15

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

seancorfield02:09:14

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

seancorfield02:09:04

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

stardiviner02:09:27

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

stardiviner02:09:48

Right, perfectly fit

emilaasa06:09:01

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

emilaasa06:09:09

how the hell did I use to work with json before

emilaasa06:09:29

Like a child eating sand

mavbozo06:09:11

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

emilaasa06:09:17

Yeah it's an optional dependency

schmee06:09:48

@emilaasa I know the feeling 😂

emilaasa06:09:21

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

marcin.k.chmiel07:09:16

So parsing json by hand? 😄

hawari.rahman1710:09:53

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

hawari.rahman1710:09:46

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.

hawari.rahman1710:09:39

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

hawari.rahman1710:09:43

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

hawari.rahman1712:09:19

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.

henrik12:09:33

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

henrik12:09:54

It can totally be done in that way as well.

henrik12:09:56

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

henrik12:09:59

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

hawari.rahman1712:09:39

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

henrik12:09:53

Yeah, that would be it 🙂

hawari.rahman1712:09:54

My mistake, I tend to forgot things like this

henrik12:09:14

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

henrik12:09:51

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

hawari.rahman1712:09:59

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

hawari.rahman1712:09:36

Glad that I posted it in #beginners

henrik12:09:32

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.

henrik12:09:54

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.

henrik12:09:56

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

hawari.rahman1712:09:10

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

henrik12:09:57

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

henrik12:09:16

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

hawari.rahman1712:09:52

It's the same, I gathered benchmark using time

henrik12:09:22

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

hawari.rahman1712:09:25

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

henrik12:09:44

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

hawari.rahman1712:09:09

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

hawari.rahman1712:09:57

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

hawari.rahman1712:09:04

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

henrik12:09:49

Glad to help 🙂

alexmiller14:09:01

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

henrik15:09:09

Yes, of course! (I had no idea)

alexmiller14: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

denisgrebennicov17:09:41

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

denisgrebennicov17:09:48

is step function just +

dadair17:09:18

(* 3 1 2 3)

dadair17:09:30

No worries! 🙂

denisgrebennicov17: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?

dpsutton17:09:03

are you sure the partition is the slow part?

noisesmith17:09:32

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

denisgrebennicov17:09:05

my procedure was doing something like this

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

denisgrebennicov17:09:25

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

denisgrebennicov18:09:31

Thinking of doing for with subvec in :let clause

noisesmith18:09:08

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

trailcapital18:09:12

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

denisgrebennicov18:09:23

just not used to mapcat yet. Great point

dpsutton18:09:15

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

denisgrebennicov18:09:20

still timeout. Now it's like this

denisgrebennicov18: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))))

dpsutton18:09:28

min and max are first and last respectively

denisgrebennicov18:09:09

😄 sorry guys 😄

dpsutton18:09:33

what's the problem that you are solving

dpsutton18:09:44

what's the biggest smallest difference between k values?

denisgrebennicov18:09:19

find the subarray with min fairness

denisgrebennicov18:09:28

whereby fairness is max-min of the subarray

denisgrebennicov18:09:43

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

denisgrebennicov18:09:56

there are nth, get, and something else ?

denisgrebennicov18: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))))

denisgrebennicov18:09:17

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

dpsutton18:09:23

did it work?

denisgrebennicov18: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 ?

denisgrebennicov18:09:10

seq, list, vec is a function itself?

denisgrebennicov18:09:19

@hiredman exception is preferred instead of nil?

denisgrebennicov18:09:26

in case of out of bounds

hiredman18:09:19

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

hiredman18:09:17

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

denisgrebennicov18:09:26

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

denisgrebennicov18:09:59

sort-by then first? 😄

hiredman18:09:15

user=> (doc min-key)
-------------------------
clojure.core/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.
nil
user=> 

tobias.vetter18:09:47

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

dpsutton18:09:40

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

andy.fingerhut19:09:26

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

denisgrebennicov19:09:38

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

dave.a.roberts20:09:05

(println "Hello Clojurians")

seancorfield21:09:29

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

noisesmith21:09:37

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

denisgrebennicov21:09:14

how can I find min lexicographic string in the seq

denisgrebennicov21:09:42

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

denisgrebennicov21:09:48

but compare doesn't work in this case

denisgrebennicov21:09:13

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

dpsutton21:09:32

why are you comparing them to empty strings

dpsutton21:09:39

(sort ["bob" "apple"])

denisgrebennicov21:09:30

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

denisgrebennicov21:09:58

want to generate some kind of value for string

denisgrebennicov21:09:03

and by this value find the min

dpsutton21:09:04

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

denisgrebennicov21:09:39

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

denisgrebennicov21:09:47

how should I proceed without sorting

dpsutton21:09:50

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

dpsutton21:09:04

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

dpsutton21:09:45

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

denisgrebennicov21:09:20

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

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

ghadi21:09:33

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

ghadi21:09:48

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

denisgrebennicov21:09:58

But reduce with compare sounds very good. Thanks!

andy.fingerhut22:09:56

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.