Fork me on GitHub
#clojure
<
2022-11-07
>
M J13:11:57

Question, how can I update 2 values at least at once in a map? For example, I do this where I tae the date and apply a function where it returns "time-ago" like instead of date, returns "5 days ago":

(map #(update % :created_at (constantly (time-ago (:created_at %)))) @data-combined)
I wanna do the same for :updated_at, for instance:
(map #(update % :updated_at (constantly (time-ago (:updated_at %)))) @data-combined)
How can I do both at the same time?

p-himik13:11:16

Given that both those calls to update use a constantly function, you can just use assoc with two kv pairs. And you can always combine multiple calls to update or any other functions with e.g. ->.

Hendrik13:11:23

And the constantly function is not needed in this case because it is created newly on each iteration. So a (map (-> (update :created_at time-ago) (update :updated_at time-ago)) @data-combined) should be fine

p-himik13:11:13

Almost. Gotta turn that -> into a function. Either with #(...) and % or with (fn [...] ...). And yeah, I didn't notice that the same field was passed to time-ago so consequent application of update makes more sense than a single assoc.

Hendrik13:11:33

You are right. I missed that. Sorry could not test on my laptop before posting …

M J13:11:52

Right! Thatnks. assoc worked for both, and now I changed it to this also and works too:

(map #(-> % (update :created_at time-ago) (update :updated_at time-ago)) @data-combined)

👍 2
🙏 1
M J13:11:48

Can I also add a new key based on some condition in the map? Like a new key for each called :type ?

p-himik13:11:56

You can do anything with a combination of assoc/`update`/`dissoc`. There's also cond-> that might be useful. And condp. And many, many other things.

M J13:11:39

Okay yeah its working. Thanks a lot!! 🙏

Joshua Suskalo15:11:27

remember that the thing passed to map is a full function, so you're allowed to use things like if, let, and other constructs like that within them.

winsome17:11:14

I've got a library that's giving me a Java JsonStructure (https://www.oracle.com/technical-resources/articles/java/json.html) - is there an existing JsonStructure -> clojure wrapper?

winsome14:11:30

I just ended up stringifying it and then parsing the json string

nwjsmith18:11:18

If you need a more performance, it's a few lines of code to parse into Clojure's data structures:

(defprotocol Parseable
  (parsed [x]))

(extend-protocol Parseable
  JsonArray
  (parsed [x]
    (into [] (map parsed x)))
  JsonObject
  (parsed [x]
    (into {} (map (fn [[k v]] [k (parsed v)]) x)))
  JsonNumber
  (parsed [x]
    (if (.isIntegral x)
      (.longValue x)
      (.doubleValue x)))
  JsonString
  (parsed [x]
    (.getString x))
  JsonValue
  (parsed [x]
    (case x
      JsonValue/TRUE true
      JsonValue/FALSE false
      JsonValue/NULL nil)))

(with-open [reader (Json/createReader (io/reader (io/resource "test.json")))]
  (parsed (.read reader)))

winsome15:11:46

This worked great, though for some reason I couldn't extend the protocol to the JsonStructure interfaces, I had to extend to the classes that implement them. But that's fine, I don't need the flexibility. 👍

agorgl19:11:02

Is there a more idiomatic way to write {:id (:id peer)} ?

Al Z. Heymer08:11:48

You can also use destructuring:

Al Z. Heymer08:11:31

(let [{:keys [id]} peer]
  {:id id})

emccue10:11:04

(select-keys peer [:id])

☝️ 1
emccue10:11:12

Depending on your sensibilities

simongray12:11:31

I think select-keys is most idiomatic in this case.

hiredman19:11:54

clojure.core/select-keys

👍 1
Ferdinand Beyer19:11:07

clojure.core even 🙂

hiredman19:11:20

I must have been thinking of clojure.set/rename-keys

agorgl19:11:42

Yeah I thought so