Fork me on GitHub

I'm doing an exercism problem involving Big Decimals and I'm failing the last couple of tests due to what I think is some kind of precision error:

; FAIL in (annual-balance-update-large-positive-balance-test) (NO_SOURCE_FILE:54)                                           
; expected: (= 1016.210101621M (interest-is-interesting/annual-balance-update 1000.0001M))                                  
;   actual: (not (= 1016.210101621M 1016.2101016209999M))


The function is just:

(defn annual-balance-update                                                                                                 
    (+ balance 
       (* 0.01 (.abs balance) (interest-rate balance)))))
where interest-rate returns a double like 1.621


The other failing test is:

; FAIL in (annual-balance-update-huge-positive-balance-test) (NO_SOURCE_FILE:57)                                            
; expected: (= 920352587.26744292868451875M (interest-is-interesting/annual-balance-update 898124017.826243404425M))        
;   actual: (not (= 920352587.26744292868451875M 920352587.267443M))      
which seems to be the same issue of precision.


I've tried turning everything in that fn to a Big Decimal and such but my answer isn't changing.


Doubles are contagious, so interest rate returning a double will cause imprecise double math to be used for the whole expression


Interesting. The exercise required the interest rate to return a double. When I convert the interest rate to a BigDecimal in the annual-balance-update fn I still get the same incorrect precision.


have you tried with-precision?


i will either do that or define an appropriate EPSILON and have a equal-within-tolerance? test helper.

randomm char14:01:16

This may or may not be helpful user=> (* 0.1 0.2) 0.020000000000000004 user=> (bigdec (* 0.1 0.2)) 0.020000000000000004M user=> (* (bigdec 0.1) (bigdec 0.2)) 0.02M user=> (= (* (bigdec 0.1) (bigdec 0.2)) (bigdec 0.02)) true


Yeah, the solution was to multiply by 0.01M instead of 0.01 which I was sure I had tried early on in the process. Thanks folks.

jason poage09:01:30

im using clj-http, and when my server sends a 422 response, clj-http throws an exception inside my try-catch statement, and i cannot read the response, which is in json. i can read the response body on postman, just not sure how to get past the exception. If i don’t use try/catch, clojure gives me an error. not sure where to go from here


you can use option :unexceptional-status to specify that 422 should be treated as OK response


there are other options as well. for example: with :throw-exceptions false instead of exception thrown from clj-http you will get normal ring response if you want to handle status yourself


Got this error trying to install deps-new tool, any idea please? Execution error (ExceptionInfo) at (git.clj:45). Library io.github.seancorfield/deps-new has invalid tag: v0.4.9


Tried with v0.4.8 and got same error. Something wrong on my side? clojure -Ttools install io.github.seancorfield/deps-new '{:git/tag "v0.4.8"}' :as new Execution error (ExceptionInfo) at (git.clj:45). Library io.github.seancorfield/deps-new has invalid tag: v0.4.8


Are you on windows using cmd ?


Yes, installed CLI via scoop.


Thank you. It was quote issue. This one worked - clojure -Ttools install io.github.seancorfield/deps-new '{:git/tag ""v0.4.9""}' :as new

👍 1
Alastair Hole13:01:20

I was having warnings about SL4J defaulting to a noop backend, I added [ch.qos.logback/logback-classic "1.2.10"] and it seems happy with this and now I can see logs output to the console. Is this sufficient, or is there a more suitable or ‘standard’ alternative?


Hey team curious q: I know read-string can execute arbitrary code. What is an example of such an execution? (i.e an example of some code a nefarious user could write, which when run by read-string, borks us)

Ben Sless16:01:21

(read-string (slurp url))


(read-string "(slurp \"\")") just returns the form for me

Alex Miller (Clojure team)16:01:04

it can construct arbitrary Java classes using # or run arbitrary code with #=

❤️ 1
Ben Sless16:01:42

I mean the string passed to read string will call read string on a slurped file

Ben Sless16:01:06

Letting you load arbitrary code from outside. Fun :)

Alex Miller (Clojure team)16:01:15

(read-string "#=(launch-missiles)")

💥 4

here’s a very concrete example with arbitrary shell access

(read-string "#=( \"echo\" \"hi\")")


That ClojureDocs page still holds up well. The Clojure version numbers mentioned seem pretty old now 🙂


Concrete example:

$ clj                                                                                                                                                                                                 Clojure 1.10.3
user=> (read-string "#=(java.lang.System/exit 1)")


❤️ 1

Veery good to know. Thanks team!

Eddy Emmanuel Asturiano Peralta20:01:04

Is anyone using VSCode with the Calva extension? I got the library working on my script and so far everything's working as intended but it's throwing me "unresolved symbols" errors. I installed SICMUtils from using the depens.edn option. And it worked! I CAN use SICMUtils, only issue is that in my script if I use SICMUtils an unresolved symbol error is thrown like on the image I linked. Any ideas how to solve this?

Sam Ritchie21:01:07

The problem is the macro in my getting started example!

👀 1

Perhaps you can add a hook to an exported clj-kondo which expands in a :refer [x y z] thing so clj-kondo knows what vars are imported from SICMUtils


I think we discussed this issue before, somewhere, not sure

👍 1
Sam Ritchie23:01:44

We did! I avoided it as an emacs user, but this was the ticket


In emacs you will have the same problems I think.


but yes, the approach described in the issue would still be what I would recommend, or hardcode (programmatically perhaps) the vars in the hook expansion. that would be even more robust.

Sam Ritchie23:01:29

I should have said, as an emacs user with an old pre-clj-kondo config :)

Sam Ritchie23:01:51

I will bump this way up! And turn on kondo for myself


ok let me know if you need help, we will fix it


off to bed now 💤

Eddy Emmanuel Asturiano Peralta03:01:45

Hold up, made a new project with the exact same deps.edn file and the issue seems to have magically solved itself (image of my .clj file linked) :thinking_face:. I have the suspicion the bug is on the Calva extension side, unless I did something different I haven't noticed yet.

Eddy Emmanuel Asturiano Peralta03:01:54

Yup, on my other file the linting error is like stuck somehow.

Sam Ritchie05:01:35

very strange, @easturiano! well, I still have some tidying to do with my clj-kondo integration so I wouldn’t be surprised if you hit more stuff. but this is good news!

Sam Ritchie05:01:58

@easturiano also would love to hear what you’re up to with #sicmutils, ask any Qs and feel free to chat whenever!


@easturiano How are you making the symbols available in that file? what does your ns form look like?

Eddy Emmanuel Asturiano Peralta21:01:55

I was following one of the begninner's tutorials so in my src/playground.clj file I only typed in (ns playground) (require '[sicmutils.env :as env :refer :all])

Eddy Emmanuel Asturiano Peralta21:01:44

From the tutorial I additionally made a deps.edn file on the same directory and copy pasted {:paths ["resources" "src"]  `:deps {org.clojure/clojure {:mvn/version "1.10.3"}`         nrepl/nrepl {:mvn/version "0.9.0"}         sicmutils/sicmutils {:mvn/version "0.20.1"}}}

Sam Ritchie21:01:58

Interesting, :refer :all should totally work. I have that issue when I use (require '[sicmutils.env :as env]) (env/bootstrap-repl!)

Sam Ritchie21:01:28

I can try to recreate when I get to a machine, but it would be great if you could paste the full contents of the file that causes those linting issues

Eddy Emmanuel Asturiano Peralta22:01:50

My file is src/playground.clj and its contents are

(ns playground)

(require '[sicmutils.env :as e :refer :all])

  (- (* 7 (/ 1 2)) 2)
  (asin -10)
And asin it throws this error: "resource": "/home/eddya/cljProjects/test/src/playground.clj", "owner": "generateddiagnostic_collection_name_#0", "code": "unresolved-symbol", "severity": 8, "message": "Unresolved symbol: asin", "source": "clj-kondo", "startLineNumber": 7, "startColumn": 4, "endLineNumber": 7, "endColumn": 8 }] Also there´s a linting warning on :all [{ "resource": "/home/eddya/cljProjects/test/src/playground.clj", "owner": "generateddiagnostic_collection_name_#0", "code": "refer-all", "severity": 4, "message": "use alias or :refer", "source": "clj-kondo", "startLineNumber": 3, "startColumn": 39, "endLineNumber": 3, "endColumn": 43 }]


Ah, looks like sicmutils uses potemkin to import vars from other namespaces so that isn't going to be something that clj-kondo understands, because those vars aren't actually defined in the sicmutils.env namespace .

Sam Ritchie21:01:10

It is not quite that, it is this macro I created to simulate :refer :all for cljs users :(

Sam Ritchie21:01:23

Good news is that is not needed in clj only, so I can help here


clj-kondo understands potemkin


but you do need to lint your dependencies, there might be an issue with that


repro welcome


@borkdude As a beginner, I doubt Eddy will be able to create a repro for you...?


without a repro, I can't repro


perhaps @sritchie09 also has an idea what's going on, as the author of #sicmutils

👍 1

Do not know if this is a good chat but how do I start a shadow-cljs/reagent server so the project is compiled and the server is started so I can show the app on a website. I remember it's something as npx ..


. The command is npx shadow-cljs watch app where watch is either watch to keep recompiling on change, or compile to compile once. The argument app is whatever you named the build in your shadow-cljs.edn file


Hey folks! Does anyone know if it's possible not eval a *data-readers*? I would like to do something similar what the quote does with a form.

(defn not-eval-form
  '(+ 1 2 3))

 (not-eval-form) ;; => (+ 1 2 3)
;; Assuming that the *data-readers* are
;; { hey/dont-execute-it clojure.core/inc }
(defn not-eval-data-reader
  ;; Do something magic on that step
  {:foo #hey/dont-execute-it 5})

 (not-eval-data-reader) ;; => 6

;; But I would like to return something like
(not-eval-data-reader) ;; => {:foo #hey/dont-execute-it 5}


it is possible, but the way to do it is to make a function that returns a list that starts with the symbol quote


better to just use quote


'foo is short hand for (quote foo) which is a list of two symbols quote and foo


which a list where the first symbol is quote is evaluted the result is just the second part of the list, in this case the symbol foo


the way the reader works is it constructs datastructures (lists, symbols, maps, etc) that are then evaluated


the way data readers work, is they allow you to have a custom function that is called and returns its own datastructures to be evaluated


something to keep in mind is not everything can be quoted successfully


quoted things have pass through the evaluator, and clojure's evaluator compiles to jvm bytecode


so whatever is quoted, the compiler has to know how to serialize it in someway in bytecode, and then reconstruct it from there


Clojure 1.10.2
user=> (set! *data-readers* (assoc *data-readers* 'foo (fn [x] (Object.))))
{foo #object[user$eval1$fn__137 0x7aad3f7d "user$eval1$fn__137@7aad3f7d"]}
user=> #foo 1
#object[java.lang.Object 0x6f667ad1 "java.lang.Object@6f667ad1"]
user=> (fn [] #foo 1)
Syntax error compiling fn* at (REPL:1:1).
Can't embed object in code, maybe print-dup not defined: java.lang.Object@388b401d
user=> (set! *data-readers* (assoc *data-readers* 'foo (fn [x] (list 'clojure.core/+ 1 1))))
{foo #object[user$eval143$fn__144 0x78faea5f "user$eval143$fn__144@78faea5f"]}
user=> #foo 1


Thank you so much for the answer but I in my case I wouldn't like to execute the code of the data-readers, for example:

(set! *data-readers* (assoc *data-readers* 'foo (fn [x] (list 'clojure.core/+ 1 1))))
When calling the data-reader the desirable result should be something like that:
(fn []
{:a #foo 1})
=> {:a #foo 1}
But currently the result is
{:a 2}


I don't really know if it's possible since as far as I know the reader step is made before the evaluation. But I don't have sure about that


@U0NCTKEV8 I don't know if I was clear enough, please let me know if I need to elaborate the question a little bit more.