Fork me on GitHub
#beginners
<
2021-04-08
>
zackteo01:04:19

Just to double check, how do I best in a string of json like a response from a http api call. Do I use data.json or is there something in built like read-string >

hiredman01:04:07

The two main libraries are going to be data.json or cheshire. data.json is a lightweight from scratch clojure json library, cheshire is built on jackson which weighs in substantially heavier

hiredman01:04:40

I am pretty anti-dependency these days, the last personal project I did I hacked together just enough of a json encoder to avoid having any dependency for it

hiredman01:04:49

At work we just had a big push to switch to data.json from cheshire everywhere, but we still could get rid of our Jackson dep (some other java libraries bring it in)

hiredman01:04:52

https://git.sr.ht/~hiredman/lions/tree/master/item/src/com/manigfeald/json.clj is the hacked together encoder, not correct for all data, but generates correct json for the data I feed it

seancorfield01:04:39

@zackteo Yup, what @hiredman said. Now that data.json has had a big performance overhaul courtesy of @slipset I would say try to use that for all situations unless you have something that is so performance-critical you need to look at Jsonista (built around the problematic Jackson libraries).

seancorfield01:04:00

data.json 2.1.0 just came out with UUID support, so the main difference between data.json and Cheshire is the latter has built-in date support, but with the former and its :value-fn option, you can manage dates pretty easily (IMO).

seancorfield01:04:38

Cheshire has a lot of optional functionality, based on what you have on your classpath, but it's very popular and tends to get dragged in via several other popular community libraries, so you can end up with quite a mess of transitive dependencies... which I'm increasingly frustrated with these days.

zackteo01:04:24

Alright! Thanks 🙂 Yeah I saw your posts about getting managing dependencies and doing the best to get with of jackson . Performance definitely isn't too much a concern so data.json would work

Michael Lan03:04:29

I’m trying to use the #inst reader macro to create an instant time for a Datomic database. But I want this time to be programmatic: for instance, here I am trying to make a new inst from the current time:

#inst (current-time)
But i suspect this doesn’t work because the #inst sees a list, not a string. Is there a way to make this work?

andy.fingerhut03:04:21

#inst is for writing constant date+time values in Clojure, not run-time variable values: https://clojure.org/reference/reader#_built_in_tagged_literals

andy.fingerhut03:04:13

If you want to create a Clojure data structure with a run-time variable data+time value inside of it, just call whatever function or method you want that returns the desired value, e.g. (current-time)

andy.fingerhut03:04:36

Note: I do not know if current-time in your example is a function in your code base -- I am not aware of any such function built into Clojure, but there are several Java APIs for getting the current data and/or time, e.g. those in the java.time package: https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

Michael Lan03:04:22

Yea… my current-time function is just

(defn current-time []
  (java.time.LocalDateTime/now))
But it seems that is very near to what #inst does anyway. I think I can figure this out from here, thanks a lot!

pinealan08:04:21

Recommendations for a lightweight library websocket client on JVM?

flowthing08:04:06

Or if you want a wrapper, you could look into e.g. https://github.com/gnarroway/hato#websockets

Joe11:04:09

Hi, I was watching Stu Halloway's talk Running With Scissors, and he mentioned the 'inverted REPL' he wrote for his personal financial software. It includes a snippet

(let [action (edn/read in)
      result (perform-cat-action action conn ftx)],,,)
With the idea being he provides an action by writing edn to indicate action which is then processed. I'm fiddling with something similiar, and I was wondering what the in variable would be here. I was thinking stdin, but the way he described it, it's sounds like he's inputting via the REPL itself. Is that possible, and if so, how would in be defined to read from the REPL?

jumar14:04:08

Perhaps it was *in* meaning STDIN?

Audrius12:04:21

I wonder what is the difference between clojure.java.jdbc and clojure.jdbc ?

noisesmith14:04:55

clojure.jdbc is a defunct project IIRC, and it attempted to be a more clojure flavored alternative to clojure.java.jdbc

noisesmith14:04:50

"The project is tested under JDK7 and JDK8."

ghadi15:04:44

clojure.jdbc was an unfortunately named library

ghadi15:04:51

namespace squatting

manutter5112:04:42

I don’t recall seeing clojure.jdbc before, but this post may be of interest: https://corfield.org/blog/2019/07/04/next-jdbc/

NoahTheDuke13:04:53

also checkout #sql for discussions of next.jdbc

sova-soars-the-sora16:04:09

I have 2 maps,

;author-id and nick
{:author-id "1", :nickname "nic"}

;author-id and post-content
{:author-id "1", :post-content "h4x"}
I want to merge :nickname into the author-id and post-content map. is there a simple way to do that on matching :author-id ?

dpsutton16:04:59

if all the data is consistent, you could group-by author-id and then apply merge to the maps that are grouped by that key

dpsutton16:04:17

that is, if all the data is either disjoint or where it coincides it agrees

sova-soars-the-sora16:04:54

It oughta be consistent, yeah, I think that is reasonable to expect.

sova-soars-the-sora16:04:32

I think it makes more sense to have an indexed map, now that I try reasoning about it in the REPL...

{"1" {:author-id "1" :nickname "S"} "2" {:author-id "2" :nickname "R"}}

sova-soars-the-sora16:04:49

so maybe smashing them together on matching index is possible in a simple way?

raspasov16:04:04

@sova It’s not very clear to me what you’re trying to do precisely; Do you have a sequence of many maps that all have :author-id in them? Because if you only have just 2 maps that look exactly like those, you can just (merge m1 m2) 🙂

sova-soars-the-sora16:04:57

(def posts (atom {"1" {:author-id "1" :post-content "SNnax"} "2" {:author-id "2" :post-content "Drolle"}}))
(def nicks (atom {"1" {:author-id "1" :nickname "Vace"} "2" {:author-id "2" :nickname "Luke"}}))
I'd like the result:
{"1" {:author-id "1" :post-content "SNnax" :nickname "Vace"} "2" {:author-id "2" :nickname "luke" :post-content "Drolle"}}

sova-soars-the-sora16:04:17

I thought this is what merge was for but I'm not getting the expected result

dpsutton16:04:29

i think you could (merge-with merge here

raspasov16:04:12

(clojure.set/join
 [{:author-id "1" :post-content "SNnax"}
  {:author-id "2" :post-content "Drolle"}]
 
 [{:author-id "1" :nickname "Vace"}
  {:author-id "2" :nickname "Luke"}])
=> #{{:author-id "1", :post-content "SNnax", :nickname "Vace"} {:author-id "2", :post-content "Drolle", :nickname "Luke"}}

sova-soars-the-sora16:04:36

Okay i'm not indexing by user-id though, I am indexing posts by post-id and users by user-id... so my apologies my needs are a little different. I think it's more like "find and replace" where I want to inject the nickname into the post-map

sova-soars-the-sora16:04:54

(def posts (atom {"eee9" {:author-id "1" :post-content "SNnax" :post-id "eee9"} "eeea" {:author-id "2" :post-content "Drolle" :post-id "eeea"}}))
(def nicks (atom {"1" {:author-id "1" :nickname "Vace"} "2" {:author-id "2" :nickname "Luke"}}))
(notice posts indexing changed, post-ids (their index) live inside each map as well) Desired result: posts map with correct nickname injected
{"eee9" {:author-id "1" :post-content "SNnax" :nickname "Vace" :post-id "eee9"} "eeea" {:author-id "2" :post-content "Drolle" :nickname "Luke" :post-id "eeea"}}

sova-soars-the-sora17:04:59

Maybe I'll just start writing nicknames straight into the posts atom, and do find-and-replace if the nicknames ever change.

sova-soars-the-sora17:04:21

thanks for the help it's much appreciated

ndonolli17:04:53

@sova a little late but you could do

(reduce-kv 
  (fn [m k v] 
    (assoc m k (merge v (get nicks (:author-id v))))) 
  {} posts)

🥲 3
3
ndonolli17:04:04

not exactly find-and-replace, but useful if you want to to merge posts into nicks

Michael Lan17:04:38

To mitigate Clojure’s slow startup, I want to have a running nREPL in the background and then periodically run babashka scripts. Is it possible for babashka to interact with the REPL? I know the nREPL exposes a port but how do I interact with it without the nrepl package on the babashka end?

Michael Lan17:04:50

This library isn’t documented under the “Libraries” section, so I got confused. Thanks borkdude

borkdude17:04:29

@michaellan202 which library do you mean?

Michael Lan17:04:21

Oh, nevermind. I was mistakenly Cmd-F’ing for “nrepl” when the library is called “bencode.” Silly me

borkdude17:04:51

Understandable. Maybe a babashka.nrepl-client library would be nice in time, but this is the low level way how to do it

byrongibby21:04:29

Hi. I have a question about reify , I'm not sure where to post it, so I'll try here. I don't understand why my code is returning java.lang.Object and not java.lang.Double? I am trying to reify a functional interface from http://generated.ojalgo.org/org/ojalgo/function/PrimitiveFunction.Unary.html.

(reify
  org.ojalgo.function.PrimitiveFunction$Unary
  (invoke [this ^Double arg]
    (double arg)))
Returns
; eval (current-form): (reify org.ojalgo.function.PrimitiveFunction$Un...
; (err) Syntax error (IllegalArgumentException) compiling reify*
; (err) Mismatched return type: invoke, expected: java.lang.Double, had: java.lang.Object
Any help would be greatly appreciated :)

schmee21:04:30

you need

(invoke ^double [this ^double arg]
    arg))
see https://clojure.org/reference/java_interop#primitives for more info!

byrongibby21:04:08

Works perfectly, thanks!

byrongibby21:04:59

I have

(^double invoke [this ^double arg]
    arg))

schmee21:04:55

type hints can go before the name or the args list, before args list is preferred since before name doesn’t work for functions with multiple arities :thumbsup:

💡 3
Vachi21:04:16

hi everyone, what is the recommendation for implementing money with currencies in Clojure, should it be done with Records to enforce some rigidity or just use maps with namespaced keys?

schmee21:04:47

how do you plan to represent the amounts?

Vachi21:04:18

with bigdecimal

schmee21:04:09

if you’re gonna have a ton of these things, I suggest records for performance, otherwise start with maps 🙂

👍 3
alexmiller21:04:21

Java has some libs for this too like JodaMoney

Vachi22:04:09

@U064X3EF3 yeah, but it would force us to use interop and bring many types

raspasov22:04:00

There’s this, it seems like it hasn’t been updated in a while, but I’ve used in the past (at a basic level); it worked fine https://github.com/clojurewerkz/money

raspasov22:04:40

It does wrap joda-money AFAICT

didibus01:04:01

I'd just use a map, possibly even just a vector

👍 3
agile_geek08:04:53

Just a thought but a lot of financial institutions represent currency values using long values by removing the decimal place and using the smallest currency unit i.e. cents instead of dollars or pence instead of pounds.

👍 4