Fork me on GitHub
#beginners
<
2023-07-13
>
Colin (fosskers)08:07:00

Hi there, I'd like to add portal as a dependency, but only when I'm doing local development. I wouldn't need it in the production bundle. Some languages have the notion of "dev dependencies". Does Clojure? Is there a straight-forward way to get all this to play nicely with Cider too?

dumrat08:07:20

Are you using deps or lein?

dumrat08:07:06

Not familiar with deps sry.

jpmonettas10:07:33

@U058DHAN3UP yes there is! As described in that link you can do it like this in your deps.edn :

{:paths ["src"]
 :deps {... your prod deps ...}
 :aliases {:dev {:extra-deps {djblue/portal {:mvn/version "0.42.1"}}
                 :extra-paths ["dev-src"]}}} 
Then when starting a repl you can choose what aliases to include like clj -A:dev Now for Cider you can customize what aliases get started when you jack-in by customizing the cider-clojure-cli-aliases var. If you want to have different aliases started for different projects you can create a .dir-locals.el file on your project root folder with a content like this :
((clojure-mode . ((cider-clojure-cli-aliases . "dev:dev-tools:testing-tools"))))
So when you jack in it will start a repl with those 3 aliases enable

Colin (fosskers)11:07:48

Alright nice! That sound do it, thank you

Colin (fosskers)02:07:56

It worked, thanks again!

Colin (fosskers)10:07:17

What's the go-to way to produce reasonable log messages to stdout? I don't need any sort of rocket surgery solution, just some timestamps, level labels, and the main message printed to the terminal.

pithyless11:07:10

Logging is one of those "this should be obvious" issues (like unicode, datetime, etc.) that has more tradeoffs and edge-cases the further your dig. If you have no other requirements than what you posted, I would recommend either: 1. More opinionated and "all or nothing" solution - https://github.com/ptaoussanis/timbre 2. Less opinionated and "lego bricks" solution - https://github.com/clojure/tools.logging in your own code + you need to configure a backend (e.g. via https://github.com/pyr/unilog if you don't want to dig too deep into JVM logging)

Colin (fosskers)11:07:38

Thanks I'll look into those

Colin (fosskers)03:07:12

timbre did the trick, thank you! "Just works"!

👍 2
Nathan Nolk14:07:35

Hi all, I tried writing a function that rounds a number (in my context, a Double) to the second decimal place but I can't seem to get it to work. I first simply used with-precision 2 number but it clearly didn't work, so I tried the code below but it isn't working either (it just returns number). Any idea what the problem is?

delaguardo14:07:38

(defn round-2
  "Rounds to 2 decimal places for the average length"
  [number]
  (with-precision 2 (/ (bigdec number) 1)))

delaguardo14:07:23

with-precision works with BigDecimal operations. But because your first argument for / not necessarily BigDecimal it might not apply

Nathan Nolk14:07:06

Is there a way to circumvent this or to "cast" my double as a bigdecimal?

delaguardo14:07:40

look at my example: there is a call (bigdec number)

Nathan Nolk14:07:54

Ah thank you, I will implement this!

rolt14:07:04

(with-precision 2 (* 1M number)) but precision for BigDecimal is about the number of significant numbers so it's not what you're looking for (and also a bit convoluted) (e.g. the "fixed" version of round-2: (round-2 111) => 110

Nathan Nolk14:07:14

Ah, yeah that sounds wrong, what I want is something that takes in (say) 23.54214 and returns 23.54

rolt14:07:27

it might not be the optimal way but: (double (.setScale (BigDecimal. number) 2 java.math.RoundingMode/HALF_UP)) or simply multiply for 100, cast to int, and divide by 100 again ?

Nathan Nolk14:07:48

oh I guess that second part might work I guess

Nathan Nolk14:07:08

Okay that works, thank you!

rolt14:07:45

significant numbers => I meant significant digits

Nathan Nolk14:07:35

I went with the multiply cast divide method, it's fine for my purpose since the numbers I'm looking at are all smaller than 50

didibus18:07:17

If it's just for viewing, you can use DecimalFormat

leif20:07:48

Is there any way to get Clojure's destructure syntax to cooperate with multiple cases? As in, I would like to write a function like:

(defn foo
  ([{a :left}]
   [:left a])
  ([{a :right}]
   [:right a]))

(println (foo {:left 4})) ; => [:left 4]]

dpsutton20:07:59

you can use clojure.core.match but inside of a single arity.

leif20:07:20

Okay, thanks.

leif20:07:45

Oh intersting, I didn't realize core.match is supposed to be require as clojure.core.match, very strange.

leif20:07:07

(As opposed to other core things, like core.string.

dpsutton20:07:49

(defn foo [x]
  (match/match x
    {:left a}  [:left a]
    {:right a} [:right a]))

(foo {:left 1})

leif20:07:11

Yup, thanks.

dpsutton20:07:13

it’s just it’s namespace. clojure.string, clojure.core.match . It’s not a “supposed”, just the namespaces they have

leif20:07:32

makes sense.

dpsutton20:07:34

one thing. check the macroexpansion. the match library handles lots of stuff. but it might be overkill and slower than you need for this

(macroexpand '(match/match x
                {:left a}  [:left a]
                {:right a} [:right a]))

leif20:07:09

Oh sure.

leif20:07:25

That's not the actual pattern I need, its deeper tree patterns.

leif20:07:59

Basically converting this code to ClojureScript:

(define/match (balance t)
  [(or (tree z 'black (tree y 'red (tree x 'red A B) C) D)
       (tree z 'black (tree x 'red A (tree y 'red B C)) D)
       (tree x 'black A (tree z 'red (tree y 'red B C) D))
       (tree x 'black A (tree y 'red B (tree z 'red C D))))
   (tree y 'red (tree x 'black A B) (tree z 'black C D))]
  [else t])

dpsutton20:07:05

sketch=> (do
           (let [iters 4000]
             (println "using match")
             (time (dotimes [_ iters] (using-match {:left 1})))
             (println "handrolled")
             (time (dotimes [_ iters] (hand-rolled {:left 1}))))
           (foo {:left 1}))
using match
"Elapsed time: 1254.320042 msecs"
handrolled
"Elapsed time: 1.396541 msecs"
[:left 1]

leif20:07:06

Is that time including the time it takes to do macro expansion?

leif20:07:41

Hmm...although it doesn't look like match has or. Oh well. 😞

leif20:07:19

But (understandably) Clojure complains that both patterns have an arity of 1.

leif20:07:09

(Right now the best idea I have is to switch to core.match.

theequalizer7320:07:19

Posted in #CLDK6MFMK as well Hi Folks, I’m using reitit and malli, and I’m trying to validate/coerce a response from the DB. I’ve tried with malli.core/schema and malli.experimental.lite/schema using something like

(m/schema
  [:map 
    [:key1 :int]
    [:key2 :double]])
and also
(l/schema
  {:key1 int?
   :key2 double?})
From the DB I’m getting java.lang.Long and java.lang.Double but I’m getting a 500 error with this
{:type "reitit.coercion/response-coercion",
 :coercion "malli",
 :in ["response" "body"],
 :humanized {:key1 ["should be an int"],
             :key2 ["should be a double"]}
I don’t want to parse anything. I just need to check the types from the DB and even when I’m clearly getting something like 38 or 7.99 I can’t pass the coerce response. Any hints on how to solve this?

valerauko06:07:11

my first idea would be that whatever the db returns doesn't use keyword keys

theequalizer7311:07:33

The DB returns EDN