Fork me on GitHub
#beginners
<
2022-05-25
>
quan xing04:05:38

In next.jdbc . I use sql select one record data from db. if the someone column is null in db. the next.jdbc not return the column that it is null. How can I return the all columns

table test: id cola colb colc
             1  a    null  null

(jdbc/execute-one! connectable
                       ["select * from test where id=?" id])
=> {:id 1 :cola a}
how can I get {:id 1 :cola "a" :colb nil :colc nil}

seancorfield04:05:26

That's not the default behavior. There's an optional builder that omit nil columns, but you have to choose that, e.g., via with-options to create a connectable with that :builder-fn.

quan xing04:05:20

Ok. I see it. Thank you

seancorfield04:05:37

The default behavior, using the standard builder, is to return all columns, even if they're nil. If you're getting :id and :cola as keys, you're using a non-standard builder.

seancorfield04:05:42

(because the default builder would return :test/id and :test/cola from that select)

quan xing04:05:51

yes I used jdbc-opt/as-unqualified-modified-maps

seancorfield04:05:12

and passed in some modifying function?

seancorfield04:05:22

Why? Why not use the default builder?

quan xing04:05:27

So the nil columns omitted

quan xing04:05:44

I forgot the code I wrote earlier, I think the next.jdbc omit nil columns default:grin:

seancorfield04:05:32

Well, it was doing exactly what you were telling it to do 😸

quan xing04:05:23

Yes It's very easy understand. Although my English is pool. I've been experimenting with Clojure for real projects.

1
Stef Coetzee05:05:54

Suppose one wants to take a look at intermediate results when using something like the thread-first (->) macro using println . How is this done best? Context: I’m working through Pedestal’s Getting Started guides. In http://pedestal.io/guides/hello-world-content-types, as part of refactoring a function doing multiple things into a series of functions, this function is defined:

(defn coerce-to [response content-type]
  (-> response
      (update :body transform-content content-type)
      (assoc-in [:headers "Content-Type"] content-type)))
Where transform-content is another function. One approach that occurs to me is to rewrite the thread-first macro as a let with multiple bindings, each binding fed into the next function, and use println in the let body before returning the desired result. Using this approach, the function above becomes something like:
(defn coerce-to [response content-type]
  (let [updated-response-1 (update response
                                   :body
                                   transform-content
                                   content-type)
        updated-response-2 (assoc-in updated-response-1
                                     [:headers "Content-Type"]
                                     content-type)]
    (println "INTERMEDIATE RESULT")
    (println updated-response-1)
    (println "RETURNED RESULT")
    (println updated-response-2)
    updated-response-2))
I’d appreciate any feedback on The Clojure Way™ to approach this. Thanks!

delaguardo06:05:32

(-> m
  (foo)
  (doto (println))
  (bar)
  (doto (println)))

🤯 1
Stef Coetzee06:05:06

Wow, that’s elegant. Thanks @U04V4KLKC!

practicalli-johnny06:05:13

tap> could be used instead of println, especially if the values are data structures, inspecting those vales in Portal for example https://github.com/djblue/portal

🙏 1
sheluchin20:05:30

@U04V4KLKC sweet! I was fumbling around with different ways of doing that. Your version is much better. Thank you. Unrelated, but I noticed the other day too that you include parens around single argument functions when doing threading. Is there a reason you prefer to do it that way instead of omitting the parens? > A bare symbol or keyword without parentheses is interpreted as a simple function invocation with a single argument. https://clojure.org/guides/threading_macros#thread-last I think your snippet could be shortened down to:

(-> m
  foo
  (doto println)
  bar
  (doto println))

delaguardo21:05:23

@UPWHQK562 parens make it easier to me to read through and refactor the code. if you are looking at the line foo what do you see? A symbol. But if this symbol surrounded with parens - it is no longer just a symbol, it is function call

sheluchin10:05:05

@U04V4KLKC thanks for explaining your reasoning. I agree, it does seem to add some clarity at the cost of a few harmless characters.

Rowland Watkins06:05:51

Hey @stefcoetzee I’m not sure about others, but I use https://github.com/cloojure/tupelohttps://github.com/cloojure/tupelospy function for this kind of debugging

🙏 1
Bhougland13:06:54

I was looking at spy the other day from this library. How does it compare to using the tap> functionality?

Rowland Watkins05:06:55

Based on the docs (https://clojuredocs.org/clojure.core/tap%3E), tap> appears to only return a boolean. Spy, will always return its argument, even when nil.

Shivam A08:05:18

Hello Guys, I want to build my 1st production REST microservice in Clojure. Can someone recommend me a framework where I can implement TDD, validation of requests easily.

practicalli-johnny08:05:02

It is simple to implement TDD with a REST microservice in Clojure, as the handlers should be clojure functions Suggest looking at • https://github.com/metosin/reitit (and reitit-ring) for a data-oriented way to route requests in the REST service • https://github.com/ring-clojure/ring & https://github.com/weavejester/compojure for a macro-style approach Pretty much all libraries follow the ring protocol for turning http requests into Clojure maps, so the test data for TDD is also Clojure maps https://github.com/ring-clojure/ring-mock also provides a simple way to generate mock requests (although these are clojure maps, so not essential,, but could be useful if this is the first Clojure webapp There is some general info about writing Clojure web services and some project examples at https://practical.li/clojure-web-services/ (I'm working on adding Reiti example soon)

Shivam A08:05:09

Any thoughts on http://Pedestal.io , its interceptors looks quite interesting

danieroux08:05:08

Pedestal is working great for us.

danieroux08:05:07

Here is a sketch of what you will do to "mock" requests, going through two interceptors:

(:response (io.pedestal.interceptor.chain/execute
                     {:request {:request-method :post
                                :headers {"authorization" "nope"}}}
                     [preflight-shortcircuit-interceptor jwt-decoding-interceptor]))

practicalli-johnny14:05:02

pedestal and reitit can both use the interceptor idiom I believe.

sb09:05:06

What is the easiest way to colorise output of edn data in reagent/shadow-cljs? Eg. from this`[:pre (with-out-str (cljs.pprint/pprint edn-source))]` . Without eg. codemirror6 is that possible? (example puget lib (https://github.com/greglook/puget) , just for reagent) I didn’t find on Github, but maybe somebody saw one.. or know.

bortexz11:05:45

If I have an application with multiple uses of bigdecimals spreaded through the codebase, and wanted to specify a default precision everywhere, and avoid having to use binding math-context in every case (also for performance reasons), is it fine to alter-var-root math-context to a default one for all the application? Are there any downsides to this?

bortexz12:05:45

Or, related, does the binding of math-context propagate to threads created from the thread with the binding? (Could have a top-level binding to solve my use-case if this is the case)

emccue12:05:45

it propagates if the threads are created via future (+ some other built in mechanisms)

emccue12:05:05

if you want a precision for your whole app, chances are doing the alter var root is A-ok

👍 1
vinurs13:05:36

hello, now i want to download a file to local dir, then i use

(with-open [in ( uri)
              out ( file)]
    ( in out))
but, in the server i can not download the file directly, so i need to download it with proxy, then how can i do?

Eric13:05:38

What is the best way to define a global constant at runtime? I want to read some coordinate data, set this value based on that data, then use it in functions that I run to process the rest of the data. I created this function for making a closure, but within the function that calls it, should I just (def m-per-deg-lat (m-per-deg-lat-gen some-lat)) so I can use the global from then on? Or is a closure the wrong way to do this?

(defn m-per-deg-lat-gen
  [phi]
  (fn [] (+ 111132.92
            (* -559.82 (q/cos (* 2 phi)))
            (* 1.175 (q/cos (* 4 phi)))
            (* -0.0023 (q/cos (* 6 phi))))))

sansarip14:05:44

I think the def approach is the right idea 💡

Eric14:05:24

Thank you. I'll go for that!

👍 1
Ferdinand Beyer14:05:37

Wait, are you suggesting using def from within a function? I would recommend against that

sansarip14:05:16

Nope!

(def m-per-deg-lat (m-per-deg-lat-gen some-lat))

;; 👆 And then use this value in other namespaces
I think OP was just asking whether using def was a good way of declaring “constant” values, to which I say yes! Defs are intrinsically constants.

Ferdinand Beyer14:05:13

> within the function that calls it, should I just (def Don’t do that. If you really want to define a global constant, use def without a value:

(def global-constant nil)
and then later change its value with alter-var-root:
(alter-var-root #'global-constant (constantly the-value))

Ferdinand Beyer14:05:35

@U022T96EFV3 of course, def is the way to go to define constant values, absolutely. But on top-level, not dynamically within other functions

sansarip14:05:18

Yes, I agree. I guess I didn’t think OP was asking that! But, upon closer inspection, it seems that he may be 🔍 ?

Eric14:05:09

Ohh, interesting.

Eric14:05:30

Yes, to clarify, I want to call this from within a function.

sansarip14:05:49

Ah woops :face_palm: ! Good catch @U031CHTGX1T

🙂 1
Ferdinand Beyer14:05:36

One issue with that approach is that you will lose some tool / IDE support @U032LAD66SF

Ferdinand Beyer14:05:52

Since references to the var will not resolve

Ferdinand Beyer14:05:59

…until that dynamic function is called

Ferdinand Beyer14:05:30

Alternatively, depending on where you get the phi from, you might consider just wrapping your function in memoize to avoid duplicate calculation

Eric14:05:16

I like the sound of that!

Eric14:05:33

Ok, this gives me a lot to think about. Thank you both for all the options.

👍 2
pooriaTaj15:05:01

Hi, My checkouts folder suddently does not work , I am using Calva and for no reaosn when i use go to definition hotkey , it takes me to the uneditble source code for one of my libraries . When I change something in checkouts it does not matter because it looks like my main project does not see it's checkouts folder

pez16:05:19

Can you test if it works if you disable clojure-lsp? (You can do that from the clojure-lsp item in the statusbar.)

pooriaTaj07:05:22

Hi , How are you ? Thanks for replying , I disabled and reenabled clojure-lsp but before that I changed directory to my checkouts folder and executed lein clean lein deps both on my main dir and my checkouts subdirs and it worked.

pooriaTaj07:05:41

I am not sure where this issue arises from

jmv18:05:54

with core.memozie, is there a way to constrain a given cache to a maximum size in bytes? for my use case, i would like to have a TTL cache with a maximum size in bytes.

delaguardo19:05:50

I don't know the answer but I'm curious to know if you have an effective algorithm to calculate how much memory allocates some generic object?

seancorfield19:05:23

It's tricky but probably possible. You'd have to first find some sort of way to measure the size of (Java) data structures -- there are libraries out there that can do this to some degree or another, and I think there are some Clojure-specific ones, or at least useful wrappers.

seancorfield19:05:31

Then you'd have to implement the core.cache protocol to create a new type of cache that was size-limited, based on that. Then you could compose that with a TTL cache (core.cache stuff is composable). And then finally provide that to core.memoize.

jmv19:05:51

for some more context, i have used this in java where you can specify a resource pool of a given size: https://www.ehcache.org/documentation/3.10/getting-started.html

jmv19:05:13

but i haven't taken a peek to see how they calculate this behind the scenes

seancorfield19:05:09

If you do end up building a sized cache on top of core.cache, I suspect it would be useful to others and would be a good library to have up on GitHub/Clojars. It couldn't be included in core.cache itself (assuming it depended on something like clj-memory-meter since Contrib libs cannot have "external" dependencies). I'd be happy to answer Qs about it and possibly help maintain it if it does materialize!

gratitude-thank-you 1
jmv19:05:20

thanks @U06BE1L6T! that's helpful to see

zakkor19:05:53

I have a question about macros:

(defmacro m []
`(let [~'x 12] ~'x))
How come inside this macro, I get an error if I don't use ~'? Isn't it always safe, because the let creates a new binding? Or what exactly is causing the spec error to trigger? I suspect I am completely misunderstanding things 😅

Alex Miller (Clojure team)19:05:22

what error are you seeing?

zakkor19:05:52

Oh sorry, I mean if I don't include the ~'

Alex Miller (Clojure team)19:05:19

symbols are qualified in `

Alex Miller (Clojure team)19:05:35

so the expansion is (let [user/x 12] user/x)

Alex Miller (Clojure team)19:05:53

and let only supports binding unqualified symbols

zakkor19:05:25

Ohh, okay. How come?

Alex Miller (Clojure team)19:05:44

let-bound symbols are local and never qualified

zakkor19:05:49

Because it's meant to create locals, I guess?

zakkor19:05:07

Thanks, that makes sense. So in the scenario I posted above, ~' is the correct thing to do because the binding created will always be local. But in a different scenario, we might have to use # to gensym the symbol so we dont accidentally evaluate something from the outer scope that we didn't mean to evaluate, is that right?

Alex Miller (Clojure team)19:05:24

regular quote does not expand symbols so something like this would be fine:

(defmacro m [] '(let [x 12] x))

zakkor19:05:31

Iiiinteresting

Alex Miller (Clojure team)19:05:28

but of course, it also does not do unquote evaluation

2FO21:05:24

Good day, What's the simplest way to add a sprinkle of clojurescript to an otherwise server side rendered clojure app?

practicalli-johnny22:05:59

The simplest way to add a little ClojureScript to a server side webapp would be to write the cljs code and compile it to JavaScript with cljs-build. Then include that JavaScript in the html (or hiccup) pages served by the server side app Shadow-cljs or figwheel-main are excellent tools, but probably overkill for the stated problem

👍 2
practicalli-johnny22:05:55

The https://clojurescript.org/guides/quick-start should cover the needs of the stated problem

👍 2
2FO22:05:50

Can reagent components be sprinkled in, in similar fashion?

practicalli-johnny07:05:39

Reagent components are ClojureScript functions who are managed by the reagent render function, so yes they can be included in the same way

👍 1
practicalli-johnny07:05:00

If the amount of ClojureScript grows, then there is an advantage of using figwheel-main. And if there is a need to include many JavaScript libraries via npm (many npm packages have many dependencies), then shadow-cljs support that approach very well

👍 1
nate02:05:05

An alternate approach is to use #scittle https://github.com/babashka/scittle