Fork me on GitHub
#clojure
<
2018-10-11
>
witek11:10:28

Given a sequence of maps ms and a key k. How to get the value from the first map in ms which contains a value for k without iterating/reducing over all ms?

leonoel11:10:22

if you don't care about falsey values, (some k ms)

👍 4
gv12:10:39

I need a test.check generator that produces nested maps with simple keys, but (gen/recursive-gen #(gen/map gen/simple-type-printable, %), gen/simple-type-printable) fails with IllegalArgumentException bit operation not supported for: class java.lang.Double clojure.lang.Numbers.bitOpsCast (Numbers.java:1122)

gfredericks12:10:06

@gv do you have the full stack trace?

gv12:10:42

sure, see above

gfredericks12:10:08

@gv what version of test.check are you using?

gfredericks12:10:35

ah; so maybe fixed in the alpha versions

gfredericks12:10:42

I knew it sounded familiar

gv12:10:21

yes, in 0.10.0-alpha3 it works

gv12:10:19

recursive-gen sometimes does not create the root container?

gv12:10:00

In seldom cases I got a value from the scalar-gen instead of the expected map

gv12:10:16

Is there a complementary gen/all-of in addition to gen/one-of such that two generators can be combined as follows?

gv12:10:40

Actually, the corresponding working one-of example looks as follows:

joel13:10:08

hello, I have a question regarding the usage of go-loop: with go, the function returns a channel that contains the result of the go block. what does the channel of a go-loop contains ? is there a way to leverage the returned channel so a value computed for each iteration is put into this channel ?

joelsanchez13:10:45

imo your best bet is to pass a channel from the outside and use that. btw go-loop is just (go (loop... so it doesn't have unique semantics

joel13:10:37

thanks @joelsanchez, I'm already doing that, wondering if there was a better way

mpenet14:10:53

I haven't touched it in a while, it gets the job done 😉

orestis14:10:50

Looks nice, I wanted to have a look at how executors and thread pools etc work - I’ll use this as a guiding map :)

mpenet14:10:59

created circa 2012 don't blame me for the sometimes questionable API choices 😄

borkdude15:10:01

is there an efficient way of converting a map {:a 1 :b 2} to a flat sequence (:a 1 :b 2) without flattening all the map elements?

Alex Miller (Clojure team)15:10:12

no, but reduce-kv is likely the most efficient path to accessing all k’s and v’s for a PHM (as it avoids ever constructing map entries)

Alex Miller (Clojure team)15:10:26

it would be my guess that combining reduce-kv with transients is the fastest path to that

noisesmith17:10:14

@borkdude my first instinct there would be (into [] cat m)

noisesmith17:10:52

user=> (into [] cat {:a 1 :b 2})
[:a 1 :b 2]

noisesmith17:10:45

I'm benchmarking to compare that with a simple usage of reduce-kv with a transient

noisesmith17:10:21

TIL that unlike conj which is varags, conj! only takes 0, 1, or 2 args

noisesmith17:10:58

user=> (crit/bench (persistent! (reduce-kv (fn [t k v] (-> t (conj! k) (conj! v))) (transient []) m)))
Evaluation count : 33792360 in 60 samples of 563206 calls.
             Execution time mean : 1.800892 µs
    Execution time std-deviation : 52.165518 ns
   Execution time lower quantile : 1.734716 µs ( 2.5%)
   Execution time upper quantile : 1.907247 µs (97.5%)
                   Overhead used : 1.904748 ns

Found 2 outliers in 60 samples (3.3333 %)
	low-severe	 1 (1.6667 %)
	low-mild	 1 (1.6667 %)
 Variance from outliers : 15.8045 % Variance is moderately inflated by outliers
nil

noisesmith17:10:19

user=> (crit/bench (into [] cat m))
WARNING: Final GC required 1.148392675847086 % of runtime
Evaluation count : 17838060 in 60 samples of 297301 calls.
             Execution time mean : 3.552092 µs
    Execution time std-deviation : 494.411529 ns
   Execution time lower quantile : 3.305118 µs ( 2.5%)
   Execution time upper quantile : 4.750097 µs (97.5%)
                   Overhead used : 1.904748 ns

Found 6 outliers in 60 samples (10.0000 %)
	low-severe	 1 (1.6667 %)
	low-mild	 5 (8.3333 %)
 Variance from outliers : 82.3999 % Variance is severely inflated by outliers
nil

noisesmith17:10:45

of course @alexmiller was right about the reduce-kv version being fastest

andy.fingerhut18:10:47

You can vote on this ticket if changing that interests you: https://dev.clojure.org/jira/browse/CLJ-1103

andy.fingerhut18:10:21

I do not recall whether the changes proposed in that patch do everything you might wish for.

noisesmith18:10:16

that case didn't match the case I meant:

(ins)user=> (conj [:a :b] 1 2 3)
[:a :b 1 2 3]
(ins)user=> (conj! (transient [:a :b]) 1 2 3)
ArityException Wrong number of args (4) passed to: core/conj!  clojure.lang.AFn.throwArity (AFn.java:429)

andy.fingerhut18:10:19

Looking at the -10 patch on that ticket, it looks like it does generalize conj!

noisesmith18:10:56

oh, I didn't see it in the examples, I didn't look at the patch

andy.fingerhut18:10:43

The description could be better, agreed.

andy.fingerhut18:10:49

I guess I will update it.

andy.fingerhut18:10:31

Description updated.

andy.fingerhut18:10:06

But, FYI, if it gets somewhere within top 3 voted tickets, it might get love more quickly.

andy.fingerhut18:10:37

thumbs up here appreciated, but not tracked on JIRA 🙂

simple_smile 4
idiomancy22:10:45

what's a good, simple, performant pattern for a "history", where you push something onto it and if the count is greater than the established max size, it throws the oldest value out

hiredman22:10:06

ring buffer

idiomancy22:10:09

seems like something that might have an established pattern, if not a core function

idiomancy22:10:13

ring buffer?

hiredman22:10:39

a ring buffer is word for a thing with that behavior

idiomancy22:10:54

thats awesome, I was really hoping that a word like that existed!

idiomancy22:10:37

hahaha, I love this slack. The intelligence aggregated on here is so outstanding 😆

hiredman22:10:55

one way to implement a ring buffer in something like C would be an array of a fixed size and you update it like arr[idx++%size] = whatever

hiredman22:10:23

you can translate that idea directly to clojure using a vector, or try and be fancier (a fixed size binary tree or something)

idiomancy22:10:05

ooh, that is fancy!

mfikes22:10:41

I’m curious if the perf of persistent queue is good (`conj` to add, pop to remove). Maybe a ring buffer approach is faster.

hiredman22:10:43

dunno, in some ways pqueue is similar to mod in to a vector approach, but sort of extended to not be a fixed size

hiredman22:10:07

it builds a vector and as needed seqs the vector and replaces the vector with an empty vector

noisesmith22:10:18

the gotcha with persistant queue in my experience is if someone calls rest instead of pop it silently turns from a fifo to a lifo, but doesn't error

hiredman22:10:20

for a real world usage I would likely go with mod + a vector, the binary tree ring buffer stuff was just me trying to figure out how I would get a persistent fifo queue without clojure's datastructures

dpsutton22:10:34

that implementation was a blocking queue not a sliding queue, right?

dpsutton22:10:51

when out of capacity it didn't drop its oldest value, it refused the incoming value

noisesmith22:10:34

@dpsutton with the index / mod technique, the difference is whether reading moves the index vs. writing

noisesmith22:10:45

otherwise they stay the same

dpsutton22:10:48

(push [ring datum]
    (if (and (= read write)
             (pos? entries))
      false

dpsutton22:10:02

i was looking at this. if read and write are equal don't do anything