Fork me on GitHub
#beginners
<
2022-08-17
>
seepel06:08:49

What's the most idiomatic way to rename a key in a map? I'm working with datomic and I'd like to rename all instances of :db/id to :server/id. Right now I'm throwing a dissoc and then an assoc at it like this.

(defn entity->client [entity]
  (postwalk
   (fn [entity]
     (if-let [server-id (:db/id entity)]
       (-> entity
           (dissoc :db/id)
           (assoc :server/id server-id))
       entity))
   entity))

pyry07:08:48

I'd go for clojure.core/update-keys or clojure.set/rename-keys.

pyry07:08:40

You'd still have to do the postwalk though, as those won't perform nested updates.

pyry07:08:57

Alternatively, I think you could do the rename as part of a pull query, if a pull query is something you'd be willing to consider.

seepel07:08:18

perfect, rename-keys is exactly what I was looking for! Thank you! I am already using a pull query, I think in this instance I would prefer to keep it generic, but I wasn't aware you could rename keys as part of a pull. That being said, I could picture that coming in handy later, any chance you could give me a quick example of the syntax?

pyry07:08:55

Sorry, on my mobile phone atm so not really. I think https://docs.datomic.com/on-prem/query/pull.html#as-option might have just what you need though.

seepel07:08:52

Fair enough, thanks for the pointer!

pyry07:08:59

Come to think of it though, I'm inclined to agree that having the rename as a generic postprocessing probably makes more sense.

๐Ÿ‘ 1
Jim Newton10:08:59

hi, can someone help me remember the name of a library I can't seem to find. it was created by a group in Finland (if I recall) research-group or company, it allows you to recognize sequences based on types in sort of a regular-expression-ish way. it was very much like work I've done, and i'm getting ready to try to understand the similarites and differences.

lispyclouds11:08:42

https://github.com/metosin/malli I guess is what you're looking for?

delaguardo11:08:44

https://www.metosin.fi/blog/malli-regex-schemas/ does it looks like what you are looking for?

1
delaguardo11:08:59

also there is #find-my-lib channel for such questions.

Jim Newton13:08:24

that's the one. thanks.

Jim Newton11:08:33

similar work has been done several times, each time with very different naming.

lepistane12:08:47

Hello, i got an i think a code that would fit macro but i have no idea how to make it. So

(sh "aws"
                      "logs"
                      "get-log-events"
                      "--log-group-name" "sis"
                      "--log-stream-name" log-stream-name
                      "--region" "eu-west-1"
                      "--start-time" start-time
                      "--end-time" end-time
                      "--start-from-head")
i am using clojure.java.shell to execute some command and if you've used this command before you get next-token from the response for next batch of logs. So i am using
(sh "aws"
                      "logs"
                      "get-log-events"
                      "--log-group-name" "sis"
                      "--log-stream-name" log-stream-name
                      "--region" "eu-west-1"
                      "--start-time" start-time
                      "--end-time" end-time
                      "--start-from-head"
                      "--next-token" next-token)
(the only difference is that there is --next-token as cli argument. Right now i do a recursive calls with
(if next-token
                  (sh "aws"
                      "logs"
                      "get-log-events"
                      "--log-group-name" "sis"
                      "--log-stream-name" log-stream-name
                      "--region" "eu-west-1"
                      "--start-time" start-time
                      "--end-time" end-time
                      "--start-from-head"
                      "--next-token" next-token)
                  (sh "aws"
                      "logs"
                      "get-log-events"
                      "--log-group-name" "sis"
                      "--log-stream-name" log-stream-name
                      "--region" "eu-west-1"
                      "--start-time" start-time
                      "--end-time" end-time
                      "--start-from-head"))
which is not good ๐Ÿ™‚ is there a way so that i can make it clear/nicer/better?

rolt12:08:32

(apply sh "aws" "log" "..." (cond-> [] next-token (conj "--next-token" next-token))) (you can do that for every optional arg). Alternatively, build an option map in clojure and then transform it into a vector for a more generic/flexible code.

๐Ÿ‘ 1
Ed12:08:28

I would probably look at iteration https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/iteration for turning chains of these sorts of calls into a seq

๐Ÿ‘ 1
dpsutton15:08:14

I think this is basically the motivating example for why ghadi implemented that function

lepistane18:08:10

oh yeaa nice i forgot about that one. But apply works great for my example. Thanks!

rolt19:08:27

they meant that you could implement iteration on top of the solution, so that you get a lazy seq of log, which will automatically fetch the next page once you consume the current one

๐Ÿ‘ 1
rschmukler18:08:12

Potentially odd question but is there any way to evaluate an expression in the repl without it mutating *1 *2 etc?

seancorfield18:08:35

Those are a function of how a particular REPL works so the short answer is "no" -- but can you explain a bit more about why you want to do this and what you're trying to avoid?

rschmukler18:08:59

I'm trying to wrap some expressions in cider to attempt to load the malli dev namespace (and instrument it) without parsing the clojure expression string or messing up the *1 etc bindings. So far it's all via cider but I suspect it could be cleaner / work as I wanted if I did a custom nrepl middleware instead

seancorfield18:08:45

Yeah, you're sort of battling CIDER at that point, unfortunately. You could eval (do (your-expr) *1) which would at least leave *1 with the same value, but *2 would also be that value and *3 would become the old *2 value...

seancorfield18:08:00

I must admit, I never use those unless I'm doing some really simple stuff manually in the REPL (because I never type into the REPL for "work" stuff -- I only eval code from my editor -- so those shortcut vars are irrelevant there).

rschmukler20:08:08

Yeah, I don't use anything but *1 and that's really just because cider-inspect-last-result uses it

rschmukler20:08:26

I've basically landed on conceding *2 and being done with it

rschmukler20:08:47

Anyway, thank you for the thoughts!

ahungry21:08:31

https://github.com/clojure/clojure/blob/master/src/clj/clojure/main.clj#L436 (also core/server.clj in same repo) - I tried seeing if there was any way to mess with the implementation in there (other than keeping the history yourself) - I couldn't find a good way (like shadowing set! or the *1 binding itself)

๐Ÿ‘€ 1
ahungry21:08:56

unfortunately, despite it mentioning in the doc that *1 is the last thing "printed" to the repl, the magic isn't happening in a user definable print function, but the core repl fn itself (although a small update to the source could easily add a condition to set/not set those, if support to evaluate in repl "invisibly" was desired and then approved/added by clojure team)

๐Ÿ‘ 1
rschmukler21:08:28

Appreciate you sharing the context ๐Ÿ™‚

ahungry21:08:58

was a fun dive into some clojure internals ๐Ÿ˜‚

Ed21:08:48

Cider knows how to multiplex repls to the same jvm process (or at least it used to). So you could always try running cider-connect evaling whatever you want and disconnecting again. I would have thought that *1 etc would be specific to each REPL connection ... (I've not tried this, I'm on my phone)

Roee Mazor22:08:56

Hello, Whatโ€™s the Clojure way to transform a https://clojusc.github.io/protobuf/current/javadoc/protobuf/PersistentProtocolBufferMap.html to a standard Clojure map? even when it has nested vectors and https://clojusc.github.io/protobuf/current/javadoc/protobuf/PersistentProtocolBufferMap.html in it. postwalk seems to fail due to not updating the type of the map when updating it (into {}) - fails to the nesting. motivation: weird behaviors of the the proto map

Ben Sless05:08:14

Write your own postwalk? There are only three cases to consider

๐Ÿ™ 1
Roee Mazor05:08:34

was hoping to avoid that, but will do soon ๐Ÿ™‚

Ben Sless05:08:35

Send it here if you want another pair of eyes. Should be no more than 5 lines ๐Ÿ™‚

Roee Mazor02:09:29

(defn back-to-clojure [i]
  (cond
    (sequential? i) (map back-to-clojure i)
    (map? i) (reduce-kv #(assoc %1 %2 (back-to-clojure %3)) {} i)
    :else i))
definitely not a masterpiece, but seems to work ๐Ÿ˜„

Ben Sless04:09:43

A. That's great, actually B. Maybe use mapv and not map C. Why are you posting code at 6am local time?

๐Ÿ™ 1
Roee Mazor08:09:34

A. Thx B. Will do C. I just woke up at 1 AM and started working :(

Evan Z23:08:31

I think I have a really straight forward question thatโ€™s driving me a bit nuts. I get

% npx shadow-cljs watch :app
shadow-cljs - config: /x/shadow-cljs.edn
shadow-cljs - server version: 2.19.9 running at 
shadow-cljs - nREPL server started on port 53741
shadow-cljs - watching build :app
[:app] Configuring build.
[:app] Compiling ...
[:app] Build failure:
The required namespace "machine-monitor.core" is not available.
and in src/machine-monitor/core.cljs`` I have
(ns machine-monitor.core
  (:require [helix.core :refer [defnc $]]
            [helix.hooks :as hooks]
            [helix.dom :as d]
            ["react-dom" :as rdom]))
and in shadow-cljs.edn I have
{:source-paths
 ["src"]

 :dependencies
 [[lilactown/helix "0.1.7"]
  ]

 :builds
 {:app { :target     :browser
                     :output-dir "public/scripts/"
                     :asset-path "/scripts/"
                     :modules    {:core {:init-fn machine-monitor.core/run}}}}


}
I canโ€™t figure out whatโ€™s going on here, what file paths itโ€™s trying, etc.

seepel23:08:05

I'm also a beginner, so I may be off track here. But I noticed that when I create namespaces in Cursive it always names the file with an underscore instead of a dash. You could try moving your directory to src/machine_monitor/core.cljs

Evan Z23:08:11

that did it. How frustrating. Thank you for the help!

seepel23:08:22

Great! Glad it worked :thumbsup: