Fork me on GitHub
#clojure-europe
<
2021-07-13
>
dharrigan06:07:03

Good Morning!

pez06:07:49

Morning!

mdallastella07:07:25

Morning, 2nd 💉 today! 🤞

🎉 12
mccraigmccraig09:07:16

had my 2nd 💉 on sunday @U052TDWT7 - here i think you can see my immune system kick into gear in the middle of that night, as my heart rate jumps 10-15 bpm over the course of an hour - i was feverish yday, but it seems to have mostly passed now https://photos.app.goo.gl/DTmFJQSP2TpPJdWY8

mdallastella14:07:09

My heartbeat is usually way more higher than that 😅

mccraigmccraig18:07:07

so, this rather innocuous looking expression (/ (* 100 score) max-score) just threw a

{:type java.lang.ArithmeticException
   :message "Non-terminating decimal expansion; no exact representable decimal result."
   :at [java.math.BigDecimal divide "BigDecimal.java" 1693]}
on me... obvs easy to work around for an individual expression, but i'm left wondering how many other seemingly innocuous arithmetical expressions in this codebase will explode at some point in the future because the postgres JDBC driver decided to map to a BigDecimal

Ed12:07:16

you can hook into bigdec's precision api with the (with-precision 10 (/ (* 100 1M) 3M)) too ... I've done that in the past when I needed to convert to specific representations ... and you can put that way up the stack if you have a lot of calculations and you just want to not get this exception 😉

mccraigmccraig12:07:34

oh, cool, that's useful - thanks @U0P0TMEFJ - looking at that macro, it sets a threadlocal binding - https://github.com/clojure/clojure/blob/clojure-1.10.1/src/clj/clojure/core.clj#L5100 - so perhaps most useful within a single fn or where a synchronous flow can be guaranteed

Ed12:07:17

yeah ... it depends what you're up to ... you could, for example have ring middleware that wraps all requests in that binding ... or (set! *math-context* ...) at startup ... or something else ... 😉

Ed12:07:11

so, if you know things are just going back into a db, you could make sure you bind it to something that just gets the right number of significant figures or something 😉

mccraigmccraig12:07:05

will think on it... our api handlers are doing async i/o so dynvars don't work out so well, so maybe setting the root is the sane thing to do

seancorfield18:07:14

Yeah, that trips me up from time to time (with MySQL).

seancorfield18:07:31

I try to remember to always use double literals in expressions which prevents that:

dev=> (/ (* 100 1M) 3M)
Execution error (ArithmeticException) at java.math.BigDecimal/divide (BigDecimal.java:1715).
Non-terminating decimal expansion; no exact representable decimal result.
dev=> (/ (* 100.0 1M) 3M)
33.333333333333336

mccraigmccraig18:07:46

yeah, that's my workaround too... but it's still feels like a bit of a powder-keg - was it a good decision on the part of the mysql and postgresql drivers to map to BigDecimal by default ?

vemv19:07:19

for them it was good or irrelevant... I mean for a Java author and consumer a bigdec will be conveyed by type signatures

vemv19:07:42

there's no accidental mixing of numeric types there

vemv20:07:03

perhaps an underemphasized point is that clojure.core + , / etc are notably generalized functions optimized for certain characteristics nobody forces us to use those. One can quite trivially create specialized, per-type + etc and your code will be just as clojurey as before. I found https://github.com/ztellman/primitive-math an interesting precedent in this regard

mccraigmccraig20:07:18

ah, ofc, i'm forgetting bigdec doesn't participate in the java numeric tower

mccraigmccraig20:07:27

i certainly found it surprising to get something like a NaN for a non-zero divisor though... i wonder if there are other examples like that in the numeric tower - where the result is defined, but the implementation says no in certain circumstances

mccraigmccraig21:07:44

i guess there are the boundaries around max and min for each type... so i need to add a new "take care not to accidentally let bigdecs into your arithmetic" to my internalised compendium of clojure numeric intuition