Fork me on GitHub
#beginners
<
2022-03-07
>
Hao Liang06:03:35

Hi everyone. I have a map with namespaced keys (generated by next.jdbc), how can I remove the namespace from all keys? For example, I have a map like {:myapp/a 1 :myapp/b 2} and I want to get {:a 1 :b 2}

Martin Půda06:03:39

(-> {:myapp/a 1 :myapp/b 2}
    (update-keys #(keyword (name %))))

Martin Půda06:03:11

update-keys is from Clojure 1.11

seancorfield07:03:32

Please, just try to get used to namespaced keys -- they are idiomatic in Clojure.

💯 1
seancorfield07:03:58

You do not want to "remove the namespace".

pavlosmelissinos07:03:29

@U031NJ4ERUP what should happen to {:foo/a 1, :bar/a 2, :a 3}?

Hao Liang07:03:16

@U04V70XH6 Thanks, I got it. But I want to return the database query results to the front end (javascript) as json strings, is it ok the keep the namespaced keys?

Hao Liang07:03:49

@UEQPKG7HQ In my situation, The query results are from a single database table and I can make sure that the keys are in the same namespace.

Hao Liang07:03:56

Or maybe a structure like {:foo-a 1 :bar-a 2 :a 3} is more preferable in my case.😕

seancorfield18:03:45

@U031NJ4ERUP The various JSON-producing libraries in Clojure either strip the ns by default or have an option to do so:

dev=> (require '[clojure.data.json :as json])
nil
dev=> (json/write-str {:myapp/a 1 :myapp/b 2})
"{\"a\":1,\"b\":2}"

Hao Liang23:03:25

@U04V70XH6 Thanks Sean, the middleware I used to produce JSON keeps the ns by default, I need to explore the docs.🙂

seancorfield23:03:57

That's probably based on Cheshire. Depending on the middleware, you should be able to provide some JSON options, that get passed to Cheshire, to tell it to drop namespaces.

seancorfield23:03:27

Or are you using the Metosin stuff? If so, that'll be jsonista I expect. No idea about that one.

Hao Liang00:03:08

Yes, I’m using the Metosin/reitit, I’ll explore the docs for reitit and jsonista. Thanks again for your help.👍

hiredman06:03:46

You can pass different functions to next.jdbc that effect how the keys are created

Ngoc Khuat09:03:14

Hi everyone, Can I conditionally apply macros? For example, I have 2 macros: macro-1 and macro-2, and I want to do something like this: ((if condition macro-1 macro-2) args)

clj.max09:03:59

Hm, just tried it and apparently you can't use apply with macros: Can't take value of a macro: #'user/macro-1

👍 1
dorab16:03:52

(if condition (macro-1 args) (macro-2 args))

popeye09:03:18

I have a map function like below

(map (fn [data]// some logic) input-data)
How I do two assoc function like below in clojure, (since clojure is immutable) Note that I cannot use one (`assoc data :a "A" : b "B")`

popeye09:03:22

(map (fn [data]
       // some logic
         (assoc data :a "A")
         (assoc data :b "B")
       ) 
       input-data)

Martin Půda09:03:48

(-> data
    (assoc :a "A")
    (assoc :b "B"))

👍 1
popeye10:03:05

@U01RL1YV4P7 Thanks for your response , Can I use merge ?

Ben Sless10:03:36

A. Assoc takes a variadic number of arguments, you can just "assoc all" B. Merge is slow

oxalorg (Mitesh)14:03:03

To make it more clear, this

(-> data
    (assoc :a "A")
    (assoc :b "B"))
is equivalent to
(assoc 
  (assoc data :a "A") ;; this returns a new map with A assoc'd
  :b "B"))

sheluchin14:03:08

If I have a collection of maps and want :x to appear in each map, using a default value if it doesn't already exist in the map, is there any function that helps with that? I can reduce + check + assoc to get the desired result, but I wonder if there's anything easier.

R.A. Porter14:03:22

I’d map update.

tschady18:03:15

(merge defaults my-map) . Defaults will be overwritten.

gratitude-thank-you 1
Santiago15:03:29

what’s your favorite way of going from a unix timestamp string "1646570536" to a human readable date 2022-03-06 ?

Cora (she/her)15:03:10

I'd convert to a long, multiply by 1000, and feed it into the Timestamp constructor

Cora (she/her)15:03:17

and then just do normal formatting for dates

Cora (she/her)15:03:28

but maybe it's not the best route ¯\(ツ)

Alex Miller (Clojure team)15:03:38

the proper way would be to make like a LocalDate and then use java.time.format'ers

Alex Miller (Clojure team)15:03:08

you'll need to pick a zone/offset to interpret that point in time in of course (but that's how human time works)

Cora (she/her)15:03:09

oh, fun, Instant has ofEpochSecond

👍 1
Alex Miller (Clojure team)15:03:05

Instant really needs to be converted to a date/time in the context of a zone/offset before it can be interpreted

Cora (she/her)15:03:25

oh absolutely. and it has atZone and atOffset to make that easier

Fredy Gadotti17:03:46

Corasaurus-hex is the best username that I ever seen! 😂

💜 1
Santiago16:03:14

schweeet thank you! I need to explore those docs @corasaurus-hex, my java is still pretty weak 😅

Cora (she/her)16:03:08

the time stuff is very rich

Shuky Badeer16:03:04

Hi guys, a pretty basic question please. After downloading and installing the clj CLI (Windows), I'm trying to spin up a Reveal REPL in order to beautify the outputs especially maps and Datomic records. Since I'm new to Clojure and google doesn't exactly help, I wanted to show you guys what I did: Executing the following command within the Clojure root folder (as per the github repo - https://vlaaad.github.io/reveal/):

clj -Sdeps '{:deps {vlaaad/reveal {:mvn/version "1.3.272"}}}' -X vlaaad.reveal/repl
Which should start a Reveal REPL. But instead I get the following error:
Error building classpath. Don't know how to create ISeq from: clojure.lang.Symbol
java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
// REST OF STACK TRACE
What am I missing here? And thanks in advance!

Alex Miller (Clojure team)16:03:45

can you share some of that stack trace? if you hit the + icon in the message editor and "create a text snippet" that's the best way to add a big chunk of text

Alex Miller (Clojure team)16:03:39

one thing you might be hitting is that quoting on Windows is extra awful on the command line (see https://clojure.org/reference/deps_and_cli#quoting for details)

Alex Miller (Clojure team)16:03:47

you might actually want clj -Sdeps '{:deps {vlaaad/reveal {:mvn/version """1.3.272"""}}}' instead

Shuky Badeer16:03:04

@U064X3EF3 This is the stack and the last command you sent results in the same stack. Do you think it's another Windows weird behavior? I'm used to work on Ubuntu but this time Windows is the only option. Once again thanks for ur help!

Error building classpath. Don't know how to create ISeq from: clojure.lang.Symbol
java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
        at clojure.lang.RT.seqFrom(RT.java:557)
        at clojure.lang.RT.seq(RT.java:537)
        at clojure.core$seq__5402.invokeStatic(core.clj:137)
        at clojure.core$merge_with$merge2__5964.invoke(core.clj:3066)
        at clojure.lang.ArrayChunk.reduce(ArrayChunk.java:58)
        at clojure.core$reduce1.invokeStatic(core.clj:942)
        at clojure.core$reduce1.invokeStatic(core.clj:934)
        at clojure.core$merge_with.invokeStatic(core.clj:3059)
        at clojure.core$merge_with.doInvoke(core.clj:3051)
        at clojure.lang.RestFn.applyTo(RestFn.java:139)
        at clojure.core$apply.invokeStatic(core.clj:667)
        at clojure.core$apply.invoke(core.clj:660)
        at clojure.tools.deps.alpha.reader$merge_deps.invokeStatic(reader.clj:87)
        at clojure.tools.deps.alpha.reader$merge_deps.invoke(reader.clj:84)
        at clojure.tools.deps.alpha.script.make_classpath2$run_core.invokeStatic(make_classpath2.clj:91)
        at clojure.tools.deps.alpha.script.make_classpath2$run_core.invoke(make_classpath2.clj:74)
        at clojure.tools.deps.alpha.script.make_classpath2$run.invokeStatic(make_classpath2.clj:117)
        at clojure.tools.deps.alpha.script.make_classpath2$run.invoke(make_classpath2.clj:111)
        at clojure.tools.deps.alpha.script.make_classpath2$_main.invokeStatic(make_classpath2.clj:162)
        at clojure.tools.deps.alpha.script.make_classpath2$_main.doInvoke(make_classpath2.clj:134)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.lang.Var.applyTo(Var.java:705)
        at clojure.core$apply.invokeStatic(core.clj:665)
        at clojure.main$main_opt.invokeStatic(main.clj:514)
        at clojure.main$main_opt.invoke(main.clj:510)
        at clojure.main$main.invokeStatic(main.clj:664)
        at clojure.main$main.doInvoke(main.clj:616)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.lang.Var.applyTo(Var.java:705)
        at clojure.main.main(main.java:40)
2022/03/07 18:16:03 open C:\Users\badeer/.clojure/.cpcache/5688acfd.cp: The system cannot find the file specified.

Alex Miller (Clojure team)17:03:09

seems like you are using a very old version of the Clojure CLI based on that stack - can you install the latest version?

Alex Miller (Clojure team)17:03:39

latest version is 1.10.3.1087

Shuky Badeer05:03:46

@U064X3EF3 Oh i'm using:

clj --version
Clojure 1.10.1
I'll try to use 1.10.3 but 1.10.1 isn't that old is it?

Alex Miller (Clojure team)12:03:44

The stack has namespaces that haven't existed in a couple years, I'd much rather debug the current version

Shuky Badeer14:03:27

Oh wow! That makes sense. Actually @U064X3EF3 I tried it on Ubuntu and it works like a charm there. I'll stick with Ubuntu as it's far more natural to me than windows. Thanks A LOT for your help!

Shuky Badeer14:03:54

Also switched to the newest version

Alex Miller (Clojure team)14:03:07

cool, enjoy! if you have questions on the CLI in the future, best place to put those is in #tools-deps

Shuky Badeer15:03:52

Ohh nice! So this channel is strictly for clojure beginner matters. Thanks a lot Alex!

Alex Miller (Clojure team)15:03:21

all questions welcome here, but some people only attend to specific channels so sometimes the topics are better

Fredy Gadotti20:03:51

REPL get stuck Hey guys, when I start a REPL and type something like (range 10) it prints the result. But if for some reason I type something like (range) it starts only to print the commands but not evaluating them. I'm just able to restore the REPL restarting. Why this happens and is restart the only solution?

ghadi20:03:46

(range) is an infinite sequence, and your REPL is trying to print it out

Fredy Gadotti20:03:23

I thought that as a lazy sequence it would not be evaluated if nothing was calling it for the next value.

ghadi20:03:33

that's correct, but the act of printing is demanding the realization of values

👍 1
ghadi20:03:08

if you did (def foo (range)) it would not try to print out (range), but only the var that was just defined

Fredy Gadotti20:03:36

that makes sense

ghadi20:03:52

it will try very hard 🙂

😄 2
ghadi20:03:39

I'm assuming you're using CIDER or some other nREPL based thing, because if you use the plain clj REPL, you'll see it print out incrementally

Fredy Gadotti20:03:15

I'm using IntelliJ with Cursive plugin.

ghadi20:03:52

nREPL things will try to buffer before outputting, IIRC

ghadi20:03:59

not sure how big that buffer is

Fredy Gadotti20:03:49

After a while the socket disconnect with an error 😅

Exception in thread "nRepl-session-814d6ee7-c483-4e3a-b6c2-3943cbe2a7b6" java.net.SocketException: Socket closed
	at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
	at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
	at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
	at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
	at nrepl.transport$bencode$fn__450.invoke(transport.clj:116)
	at nrepl.transport.FnTransport.send(transport.clj:41)
	at nrepl.middleware.print$send_nonstreamed.invokeStatic(print.clj:159)
	at nrepl.middleware.print$send_nonstreamed.invoke(print.clj:138)
	at nrepl.middleware.print$printing_transport$reify__843.send(print.clj:174)
	at nrepl.middleware.caught$caught_transport$reify__878.send(caught.clj:58)
	at nrepl.middleware.interruptible_eval$evaluate$fn__934.invoke(interruptible_eval.clj:123)
	at clojure.main$repl$fn__9119.invoke(main.clj:460)
	at clojure.main$repl.invokeStatic(main.clj:458)
	at clojure.main$repl.doInvoke(main.clj:368)
	at clojure.lang.RestFn.invoke(RestFn.java:1523)
	at nrepl.middleware.interruptible_eval$evaluate.invokeStatic(interruptible_eval.clj:79)
	at nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:55)
	at nrepl.middleware.interruptible_eval$interruptible_eval$fn__941$fn__945.invoke(interruptible_eval.clj:142)
	at clojure.lang.AFn.run(AFn.java:22)
	at nrepl.middleware.session$session_exec$main_loop__1043$fn__1047.invoke(session.clj:171)
	at nrepl.middleware.session$session_exec$main_loop__1043.invoke(session.clj:170)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.base/java.lang.Thread.run(Thread.java:829)
(range 10)
Error writing to client: Broken pipe (Write failed)

phronmophobic20:03:19

cider has cider-print-quota which lets you limit the size of values it will try to print. if you're not using cider, but you're still using nrepl, you can use something like https://github.com/phronmophobic/nrepl-set-print-quota-middleware

sova-soars-the-sora21:03:26

Hello I am befuddled by the use of Coercion in Reitit. For example, the JSON corecion on https://github.com/metosin/reitit/blob/master/test/clj/reitit/http_coercion_test.clj

(testing "json coercion"
      (let [e2e #(-> (request "application/json" (ByteArrayInputStream. (j/write-value-as-bytes %)))
                     (app) :body (slurp) (j/read-value (j/object-mapper {:decode-key-fn true})))]
        (is (= data-json (e2e data-edn)))
        (is (= data-json (e2e data-json)))))
What is the purpose of encoding it as a ByteArrayInputStream? And is this local on the server only? I'm really confused as to what benefits this provides and could use some clarity

Cora (she/her)22:03:00

it looks like the ring handler expects body to be a stream. so if you're not sending an actual http request that's how you can simulate an http request