Fork me on GitHub
#clojure
<
2019-04-09
>
orestis08:04:10

Hot damn the cognitect-aws API is good! Never before had done any AWS API work (I barely even know how AWS works), and I managed to cobble together a working Route53 utlity namespace in about an hour. Love it!

parrot 16
Nazral09:04:24

So, this:

labels-probs (sort-by :score >=
                              (map #(do {:score %2 :label %1})
                                   labels clean-probs))
gives me a
java.lang.IllegalArgumentException: Comparison method violates its general contract!
        at java.util.TimSort.mergeHi(TimSort.java:899)
        at java.util.TimSort.mergeAt(TimSort.java:516)
        at java.util.TimSort.mergeCollapse(TimSort.java:439)
        at java.util.TimSort.sort(TimSort.java:245)
        at java.util.Arrays.sort(Arrays.java:1438)
        at clojure.core$sort.invokeStatic(core.clj:3115)
        at clojure.core$sort_by.invokeStatic(core.clj:3119)
        at clojure.core$sort_by.invoke(core.clj:3119)
        at closs.stages.classifiers$parse_results_threshold.invokeStatic(classifiers.clj:26)
error, but clean-probs is entirely made of floats, I'm confused...

alexyakushev09:04:17

@archibald.pontier_clo There must be a NaN somewhere in the values.

alexyakushev09:04:29

NaN's cannot be compared, so the sorting algorithm freaks out.

user=> [(= ##NaN ##NaN) (> ##NaN ##NaN) (< ##NaN ##NaN)]
[false false false]

Nazral09:04:14

Ok I will try using Double/isNaN to filter them out

Nazral10:04:08

@alexyakushev can an underflow error lead to this also ?

Nazral10:04:54

Because even if I filter the NaN out, it still crashes, I printed the vector I have no NaN in my vector, but 8.690312E-37 (among other)

alexyakushev10:04:26

I don't know if underflow can cause this, but this doesn't look like an underflow to me. This number is within float range it seems.

user=> Float/MIN_VALUE
1.4E-45

alexyakushev10:04:35

Could you post your vector?

Nazral10:04:00

(0.0 0.0 0.0 0.0 0.0 3.6712243E-31 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3.2708435E-36 0.0 0.0 0.0 0.0 1.6565916E-12 0.0 1.0 0.0 8.690312E-37 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0)
(0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 5.2775614E-29 1.0 6.7907166E-7 0.0 0.0 0.0 0.0 3.689431E-32 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0)

Nazral10:04:34

Can it be that println replaces values randomly ?

alexyakushev10:04:34

Could as well exclude that possibility, try pr instead of println

alexyakushev10:04:47

Try sorting (take 10 ...) of your sequence, will it still fail?

alexyakushev10:04:02

I would do a poor man's binary search here to try to figure out who's to blame. Something like (->> (partition-all 10 values) (map #(do (println "Sorting %") (sort %))).

Nazral10:04:46

I will try that, thank you for the help

alexyakushev10:04:13

You are welcome, will be interesting to know what was the problem in the end

Nazral10:04:29

Yeah I think I won't have a choice than diving in because the problem is not even determinist it seems

andy.fingerhut12:04:40

If it is convenient to determine the distribution of types of values in the collection you are sorting, I would be curious to see the output of (frequencies (map type c1)), where c1 is your collection of values.

andy.fingerhut11:04:45

You may want to check for Float/isNaN, too. I think maybe Double/isNaN only checks for NaN's of type Double, so will not find any Float NaN values, if you have any in your data.

andy.fingerhut11:04:49

Never mind, some experiments I just ran at the REPL indicate that Double/isNaN returns true regardless of whether you give it a NaN of type Double or Float.

andy.fingerhut11:04:33

This StackOverflow answer mentions that someone encountered this exception when sorting float and/or double values, but that seems odd to me that the floating point values are not given a total order by the default comparator: https://stackoverflow.com/a/33971198

andy.fingerhut11:04:35

Do you perhaps have a mix of some Float and some Double values in your data?

erwinrooijakkers12:04:32

Does anyone have experience logging to Stackdriver using clojure.tools/logging?

erwinrooijakkers12:04:51

Using the standard appender does not do anything Dependencies:

[ch.qos.logback/logback-classic "1.2.3" :exclusions [org.slf4j/slf4j-api]]
                 [org.slf4j/slf4j-api "1.7.26"]
                 [org.slf4j/jul-to-slf4j "1.7.25"]
                 [org.slf4j/jcl-over-slf4j "1.7.25"]
                 [org.slf4j/log4j-over-slf4j "1.7.26"]
                 [org.clojure/tools.logging "0.4.1"]

                 ;; Stackdriver
                 [com.google.cloud/google-cloud-logging-logback "0.87.0-alpha"]]
Logback.xml:
<!--  -->
<appender name="STACKDRIVER" class="com.google.cloud.logging.logback.LoggingAppender">
  <!-- Optional : filter logs at or above a level -->
  <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
    <level>INFO</level>
  </filter>
  <!-- Batched logging requests get immediately flushed for logs at or above this level -->
  <flushLevel>WARN</flushLevel>
</appender>

erwinrooijakkers12:04:14

Nevermind they do show up, but in another log

erwinrooijakkers12:04:30

The default “java.log”

Nazral14:04:11

@andy.fingerhut so I tried something:

(let [clean-probs (into [] (aget result-array 0))
        labels-probs (try (sort-by
                           :score >=
                           (keep identity
                                 (map #(when (>= %2 0.0001)
                                         {:score %2 :label %1})
                                      labels clean-probs)))
                          (catch Exception e
                            (println e)))
this somehow works with no error

Noah Bogart16:04:48

Quick question, if I’m looking to build a somewhat simple event queue or pipeline for processing changes to app state, is it worth using core.async?

Alex Miller (Clojure team)16:04:03

If it’s just a series of fns, probably not

Alex Miller (Clojure team)16:04:39

If you want queuing and possibly stage concurrency, maybe so

Noah Bogart17:04:45

cool, thanks!

fenton17:04:45

(def nested-map {:a {:b 1}})
(defn my-func [m]
  ;; some magic
  )
(my-func nested-map)
;; => 1

fenton17:04:27

how to achieve the ;; some magic part?

Noah Bogart17:04:57

(:b (:a m)) is the simplest

fenton17:04:16

right...ok

Noah Bogart17:04:24

also (get-in m [:a :b])

Robert Nikander17:04:41

Wondering if people have stories of using the STM in 'real world' code. I have used atoms a lot but have yet to see a use for the STM. I see some old Java code where it looks like it could be useful, if I could ever port it, but I'd need a way to coordinate the in-memory var changes with an external commit to a DB. Some online examples of STM show "bank accounts", but with no way to connect the transaction to external storage, I don't see how that would really work past a simple demo.

fenton17:04:43

(comp :a :b)

beders17:04:23

I usually rely on a handler being called after the DB trx commits. Your memory changes could still fail though but the assumption is that the DB holds the Truth anyways

beders17:04:48

Ie. It’s not a proper 2 phase commit

Alex Miller (Clojure team)17:04:26

@nbtheduke don't forget (-> m :a :b) too :)

Noah Bogart17:04:47

ha I thought of it but didn't post! glad you did

Alex Miller (Clojure team)17:04:54

macroexpands to (:b (:a m)) but reads left to right. prob faster than get-in.

Noah Bogart17:04:59

oh wow, really?

Noah Bogart17:04:02

I didn't know that!

Alex Miller (Clojure team)17:04:40

not a difference that would likely matter, but last time I checked, yeah

Alex Miller (Clojure team)17:04:03

you're basically adding another var deref/invoke so kind of has to be

Alex Miller (Clojure team)17:04:51

I think either -> or get-in read the best, and I think that trumps other considerations

Alex Miller (Clojure team)17:04:18

(:b (:a m)) has to be read inside-out, and comp is imo always the worst thing to read

Noah Bogart17:04:50

Agreed. Reading comp feels very awkward

fenton18:04:54

i needed a quick snappy creation of a function...what do u guys prefer?

#(-> % :a :b)
(comp :a :b)

Noah Bogart18:04:17

those are different, which is the issue

Noah Bogart18:04:34

to match, the second should be (comp :b :a)

fenton18:04:15

sure, but which do you prefer to read?

fenton18:04:43

(map (juxt :total (comp :login :author)))

Noah Bogart18:04:52

that looks readable

fenton18:04:24

is that better than: (map (juxt :total #(-> % :author :login)

Alex Miller (Clojure team)18:04:05

I prefer everything to comp :)

fenton18:04:50

➡️ thx guys! 🙂

vemv22:04:26

I'm late to the party, but I heavily use something I called rcomp which is simply reverse + comp. That way things read left-to-right, just like with OOP dot notation ...and specifically, things keep flowing left-to-right in -> and ->> chains

Robert Nikander17:04:56

A digression from -> but I saw this recently and was laughing at the names of the macros. The diamond wand, the trystero furcula, etc., ... https://github.com/rplevy/swiss-arrows

Alex Miller (Clojure team)17:04:36

many have died on the hill of arrow fetishization - this is but one of many

Alex Miller (Clojure team)17:04:53

as the greeks said, moderation in all things

Robert Nikander17:04:40

Haha. 🙂 Yup. I found the first few (similar to as->) useful at least.

Alex Miller (Clojure team)17:04:16

I draw the line at understanding the word "furcula"

Alex Miller (Clojure team)18:04:38

now that one makes sense

Alex Miller (Clojure team)18:04:54

we're going to add that to core

36
upside_down_parrot 8
sheepy 4
Robert Nikander18:04:55

If you relax your eyes, it becomes a 3D diagram of the data flow, like those magic eye stereograms.

Jakub Holý (HolyJak)21:04:14

Hi! I need to merge a bunch of maps but the merge fn depends on the key. I couldn't find a shorter, simpler, easier to understand solution than copying merge-with to merge-with-kvv that invokes the merge fn as (f key val1 val2) instead of just with the two values. Or is there a better way?

dominicm06:04:28

I think tools.does.alpha has a helper like that

👀 4