Fork me on GitHub
#clojure
<
2017-12-13
>
qqq07:12:49

given a vector v and an int n what is the fastest way to drop the last n elements of v i.e. v=[1,2,3,4] n=1 -> [1,2,3]

rauh07:12:41

drop-last?

qqq07:12:21

oh, ahd I need a vector, not a lazy sedq back

qqq07:12:45

basically, I want pop-n

noisesmith17:12:09

you could benchmark (into [] (subvec v ...)) vs (nth (iterate pop v) n)

noisesmith17:12:48

I wonder if vectors are smart about using subvecs via structural sharing

noisesmith19:12:23

right what I am asking is how expensive making a vector out of a subvec is

noisesmith19:12:37

that may or may not be faster than making a vector out of a list

qqq19:12:39

I thought subvec returned a vector. If so, where is the problem of 'how expensive making a vector out of a subvec is"

noisesmith19:12:06

it doesn’t

noisesmith19:12:53

oh wait, it isn’t a vector, but might as well be one, never mind!

rdoering07:12:01

Nothing ready AFAIK, and I don't know how fast (apply vector (drop-last 1 [1 2 3 4])) would be.

schmee07:12:15

@qqq with Specter: setval (srange (count v) (- (count v) n) NONE v)

schmee07:12:27

there is probably a better way to figure out the indexes

schmee07:12:49

that will give you a vector back

abdullahibra09:12:50

what is the best to handle deeper maps in clojure with only make affect on the most inner map for example:

abdullahibra09:12:09

{:t1 {:f1 {:l1 {:name :hello}}} :t2 {:fff2 {:ll2 {:name :world}}}

abdullahibra09:12:01

what i want to achieve is handle the last map without affecting other

danielbraun09:12:48

(assoc-in map [:t1 :f1 :l1 :name] "goodbye")

abdullahibra09:12:25

@dabra that's true if the keys are equivalent

abdullahibra09:12:29

but they aren't

abdullahibra09:12:49

are transducers helpful here?

danielbraun09:12:58

what are trying to change?

abdullahibra09:12:11

most inner map only without affecting the outer structure

danielbraun09:12:39

clojure.walk/postwalk should do it

danielbraun09:12:59

recursive traversal of the tree

nblumoe09:12:46

If you have more cases like this, I would still like to encourage you to check specter. But of course it might also be that you prefer to keep going with vanilla Clojure! 👍

abdullahibra09:12:22

@nblumoe thanks, seems specter very cool, and i guess it solve my issue with handling inner data structures, is there any connection between specter and transducers ?

bronsa09:12:54

no need for specter to drop n elements of a vector

bronsa09:12:57

just use subvec

schmee10:12:03

@bronsa ahh, true! forgot about that one, much better fit in this case

nblumoe10:12:26

haha, lol. I didn’t see that there was a reference to specter already just a few lines above. 😄 Wow, I was confused 😄

abdullahibra11:12:54

@nblumoe can you help with specter question

abdullahibra11:12:38

(s/select [MAP-VALS MAP-VALS MAP-VALS :title (filterer (fn [s] (empty? s)))] res), i'm trying to select hash maps which has non-empty :title

abdullahibra11:12:56

i got this: IllegalArgumentException Don't know how to create ISeq from: java.lang.Character clojure.lang.RT.seqFrom (RT.java:542)

abdullahibra11:12:34

(s/select [MAP-VALS MAP-VALS MAP-VALS :title (fn [s] (empty? s))] res)

abdullahibra11:12:40

without filterer

abdullahibra11:12:04

@nblumoe thanks for referring this nice lib to me

abdullahibra11:12:08

another question

abdullahibra11:12:47

(s/transform [MAP-VALS MAP-VALS MAP-VALS (fn [h] ((comp not nil?) (re-find #"wow" (:title h))))] identity res) why not i got all titles with "wow" string and got all values ?

abdullahibra11:12:08

i only want to filter those which has wow string

chrisblom11:12:34

is there a good way to measure how many threads are calling a function at the same time?

chrisblom11:12:48

i'm now abusing java.util.concurrent.Semaphore with more permits than i will ever need, does anyone know a better way?

dominicm12:12:49

I notice that https://clojure.org/guides/getting_started uses an unversioned install script, this is problematic for reproducible builds. Is there an alternative url?

dominicm12:12:40

Looks like the expectation is that the linux install script will not be used by packages. But the contents will be replicated into a build step. Got it.

Alex Miller (Clojure team)13:12:07

It is versioned and there is a actually a versioned script in the same location as well. I would like it to be used by packages if possible rather than replicating stuff. If you’re working on something, please let me know.

nathanmarz13:12:19

@abdullahibra what's the input data for that code?

abdullahibra14:12:05

i'm in another situation now, if i have set of hash maps like this: [{:s1 "cool" :p1 [{:name "hello"} {:name "world"}]}, {:s2 "cool2" :p1 [{:name "wow"} {:name "world"}]}]

abdullahibra14:12:56

how can i get the full hash maps which contain "wow" in this paths [MAP-VALS :p1 :name] ?

abdullahibra14:12:14

so in this case i should get : [{:s2 "cool2" :p1 [{:name "wow"} {:name "world"}]}]

nathanmarz14:12:25

i think this is what you're looking for: (select [ALL (selected? :p1 ALL :name (pred= "wow"))] data)

abdullahibra15:12:46

@nathanmarz very good thanks 🙂

abdullahibra15:12:16

and thank you for specter

nathanmarz15:12:27

@abdullahibra sure thing, feel free to jump into the #specter channel if you have more questions

martinklepsch15:12:12

Caused by: java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:3332)
        at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
Running into this ^ in a project where I previously never had issues with heap space. The stacktrace seems to indicate that I’m trying to print an infinite seq or something like that but there’s nothing in the stacktrace telling me where it’s coming from — anyone suggestions how I could debug this? (full stacktrace: http://sprunge.us/UUGN)

reborg15:12:45

@martinklepsch I'd be tempted to say to look into a sudden grow in size of some external data dependency, assuming your code depending on some and you didn't change anything

mpenet15:12:51

could be something leaking slowly

mpenet15:12:39

having metrics on jvm heap usage helps to spot this kind of things

mpenet15:12:29

then you can also reduce the size of the heap then enable heap dumps and be ready to crawl into logs, but the few times I had to deal with that, correlation with metrics/commits when it started was enough

martinklepsch16:12:24

To my surprise I can’t find any commit that does not produce an OOM exception. 😞 I did take a heap dump and there are about 1.1M maps with dates and all kinds of things so these seem to be retained somehow, either because they are printed as the stacktrace seems to indicate or because I’m somehow holding on to the head of a sequence. Do you have any recommendations to figure out where this is happening?

martinklepsch16:12:05

I’m really stunned that this issue seems to appear even with older commits

tbaldridge16:12:04

@martinklepsch do you have access to a memory profiler (like yourkit?) they can often perform memory retention analysis. "1.4mil dates, held by these two references..."

martinklepsch17:12:53

I have no idea what happened but the issue seems to just have gone away, what the heck? 😳

the2bears17:12:57

Heisenbugs, the worst kind.

cjsauer17:12:40

Is there a variant of partition that, instead of asking for partitions of size N, I can ask for N partitions?

bronsa17:12:41

no but it's easy to write one

tanzoniteblack17:12:45

@cjsauer Not that I'm aware of, you'll have to make it yourself. It's presumably not included because in order to have exactly N partitions of roughly equal size, you have to know the size of the entire collection ahead of time, which means it's inherently unable to be lazy

bronsa17:12:57

the reason why it's not in core is that your function needs to know the lenght of the collection

cjsauer18:12:32

@bronsa @tanzoniteblack thanks guys. Ended up here:

;; adapted from 
(defn chunkify
  [values n]
  (let [cnt (count values)
        [k m] [(quot cnt n) (rem cnt n)]]
    (for [i (range n)]
      (subvec values
              (+ (* i k) (min i m))
              (+ (* (inc i) k) (min (inc i) m))
              ))))

cjsauer18:12:54

Not nearly as pretty as the Python version, but it works 🙂

noisesmith18:12:24

wait, am I missing something, why concat?

noisesmith18:12:51

oh, if I’m not mistaken that concat is a noop

cjsauer18:12:12

Ah! Yes you're right.

rauh18:12:14

@cjsauer Why not just compute the n that you'd need for partition-all?

tanzoniteblack18:12:11

something like

(defn partition-n-groups [n coll]
  (partition-all (int (/ (count coll) n)) coll))

cjsauer18:12:51

@tanzoniteblack counter example:

(partition-n-groups 3 [1 2 3 4])

cjsauer18:12:03

Returns:

((1) (2) (3) (4))

cjsauer18:12:20

@rauh I actually was initially, but I was running into edge cases like above

noisesmith18:12:26

yeah, I think you want to round up instead of down

tanzoniteblack18:12:38

agreed

(defn partition-n-groups [n coll]
  (partition-all (Math/ceil (/ (count coll) n)) coll))

noisesmith18:12:27

it’s still off

(ins)user=> (defn partition-n-groups [n coll]
  (partition-all (Math/ceil (/ (count coll) n)) coll))
#'user/partition-n-groups
(ins)user=> (partition-n-groups 3 [1 2 3 4])
((1 2) (3 4))

cjsauer18:12:45

Mhm...I'm afraid rounding just trades one edge case for another 😕

cjsauer18:12:08

Which led me to asking you all, and arriving at that Python implementation.

rauh18:12:02

@cjsauer Well what should it return? The last el dropped or the last element merged into the last collection?

cjsauer18:12:26

@rauh it should ideally keep all elements, like partition-all does

cjsauer18:12:56

As far as grouping goes, I'm not too picky. It's fine if an element ends up in any grouping.

tanzoniteblack18:12:06

@cjsauer are you trying to guarantee that you 1.) don't drop any elements and 2.) have exactly n groups in the output?

cjsauer18:12:40

@tanzoniteblack exactly that. I'm specifically dealing with n = 3, and there are guaranteed to be >= 3 elements in the input coll

cjsauer18:12:14

I should add that the sort order should remain intact

noisesmith18:12:48

@cjsauer interesting problem - I think this solves it

(defn partition-n
  [n coll]
  (let [c (count coll)
        r (rem c n)
        q (quot c n)
        N (+ q (if (zero? r) 0 1))]
    (partition-all N coll)))

noisesmith18:12:27

perhaps N should be (if (zero? r) q (inc q))

noisesmith18:12:33

(same result)

fbielejec18:12:56

Can I have a spec conformer for a map that will cherry-pick required keys? Something like:

(s/def ::bid (s/merge (s/keys :req-un [::title ::value])
                      (s/map-of #{::title ::value} any?)))

(s/def ::safe-bid
  (s/and
   (s/conformer #(select-keys % #{::title ::value}))
   ::bid))

(s/conform ::safe-bid {:title "reveal" :value 0.1 :extra "foo"})
That would return:`=> {:title "reveal" :value 0.1}`

cjsauer18:12:08

@noisesmith ah that's much cleaner

noisesmith18:12:34

could maybe use longer names, but hey it’s so mathy maybe one letter names are OK haha

cjsauer18:12:18

@noisesmith hmm...I'm getting:

=> (partition-n 3 [1 2 3 4])
((1 2) (3 4))

noisesmith18:12:49

clearly I didn’t try enough test cases

cjsauer18:12:59

runs to get test.check

noisesmith18:12:29

@cjsauer aha - there’s no way for partition-all to return a collection of length 3 if given a collection of length 4

cjsauer18:12:36

Thaaaat could be a problem haha

noisesmith18:12:50

I bet there’s still an elegant solution though…

cjsauer18:12:06

Python makes it look so nice...

cjsauer18:12:20

Practically a one-liner

tanzoniteblack18:12:39

what is the python version?

cjsauer18:12:01

Looks to be pretty standard python list comprehension

qqq19:12:23

Is there a Clojure DSL for specifying parallel computations on tensors that: on Desktop, compiles to Cuda/OpenCL and on CLJS, compiles to WebAssembly? 🙂

qqq19:12:45

"parallel Tensor Ops" seems like it should be high enough level that it's possible to efficiently target all those platforms

Drew Verlee19:12:04

Are there clojure x videos up anywhere?

shaun-mahood19:12:11

Thanks for the reminder - I haven't had a chance to watch them yet and was looking for something to watch later 🙂

madstap20:12:03

@cjsauer I made a sequence version of n-partitions, by re-using the math from the python/vector version. I wouldn't really call it an improvement in clarity though.

(defn n-partitions
  [n coll]
  (let [cnt (count coll)
        [q r] [(quot cnt n) (rem cnt n)]
        partition-size (fn [i]
                         (- (+ (* (inc i) q) (min (inc i) r))
                            (+ (* i q) (min i r))))]
    (->> (range n)
         (reductions (fn [[_ more] i]
                       (split-at (partition-size i) more))
                     [nil coll])
         (rest)
         (map first))))

zignd21:12:10

at the current state of clojure.spec, is it possible to spec multimethods?

cjsauer01:12:57

Seems not 😕

zignd03:12:38

sad :( at least in the end i ended up refactoring the code to use simple functions instead, because multimethods wasn't the correct approach

zignd03:12:48

thanks for taking your time!

borkdude21:12:55

I found a weird thing with some. I rewrote it using reduce and found it was much faster:

(defn find-first
  [pred vals]
  (reduce
   (fn [_ v]
     (when (pred v)
       (reduced v)))
   nil
   vals))
(time (some       identity (repeat 10000000 nil))) ;; 250 ms
(time (find-first identity (repeat 10000000 nil))) ;; 40 ms

rauh21:12:27

@borkdude Don't use repeat to benchmark things. Real code barely uses it.

borkdude21:12:52

@rauh ok, I tried it with other collections too, same thing

rauh21:12:30

@borkdude Yeah some uses first/next which isnt' all that fast. Reduce is usually faster. I see a 2x factor

borkdude21:12:14

(time (some #(when (> ^long % 10000000) %) (range))) ;; 558 ms
(time (find-first #(> ^long % 10000000)    (range))) ;; 95 ms

New To Clojure22:12:24

Is there a Clojure killer applications? For example, Scala has a renowned Akka.

didibus03:12:17

Clojure is the killer application. It sells itself, you don't really need anything else. For example, since you mentioned Akka, you'd probably be interested in core.async, though its just a part of Clojure.

didibus03:12:26

In terms of things made in Clojure to be used as frameworks from other languages, I guess @U5LPUJ7AP pointed to some: Datomic and Onyx. I'll add Apache Storm, Overtone, Cascalog, Riemann, Puppet, Metabase, Alda, Transit, Datascript and Quil to that list.

seancorfield22:12:53

I can't think of anything that would cause people to switch to Clojure just to use it...

seancorfield22:12:11

(mind you, Akka and Play are both probably used more by Java devs now?)

qqq22:12:53

(fn [v n] [(take n v) (drop n v)]) ^-- is there a builtin for this? to 'split' a vector at a specified index

joelsanchez22:12:57

we have Datomic and Onyx, and of course ClojureScript, which has the obvious advantage of allowing you to avoid JS 😛

arrdem22:12:58

@qqq clojure.core/split-at

noisesmith22:12:41

also you could use subvec if you want a faster op that retains vectorness

noisesmith22:12:22

ser=> (let [v [1 2 3 4 5 6]] [(subvec v 0 3) (subvec v 3 (count v))])
[[1 2 3] [4 5 6]]