For anybody who would be interested in the answer:
(defmacro named-parameters[f]
`(map keyword ((comp :keys second first :arglists meta) (var ~f))))
(defn foo [& {:keys [filename yop]}] (str filename yop))
(named-parameters foo)
It is reliable enough if you are defining the function yourself, it can be unreliable for things from libraries
ah ok, I control the functions, no issues.
Hi Guys, i'm using doom emacs now, and I don't know the shortcut for : 1. how to make my cider repl move to right panel? 2. [C c M p] >> is this the correct shortcut to send code from buffer to REPL? much appreciated for the help ๐
gotcha, 1. [SPC w v] to add window vertically 2. [SPC b B] to select the cider REPL poof we got buffer & REPL side by side vertically
FYI most of the time you don't even need the REPL buffer in the foreground
#emacs might be a better place to ask these questions
Not sure about doom emacs but with vanilla emacs:
1. you can change the orientation with C-\
.
2. In general you usually don't send the code to the repl, but you evaluate it in place instead and the shortcut for that is C-c C-c
or C-c C-e
, depending on where the cursor is. From the https://docs.cider.mx/cider/usage/cider_mode.html:
> Typically you'd begin your interaction with any source buffer by evaluating it with C-c C-k. Afterwards you'd normally evaluate just individual forms with C-c C-e (evaluate preceding form) or C-c C-c (evaluate current top-level form).
ah okay, will ask there
The deployment story of Clojure(Script) is very different than in JavaScript. On top of this, there are so many options that make beginners wonder which strategy to adopt. Experienced Clojurians, would you mind sparing a minute and share what you think are the state-of-the-art (or your favourite) deployment strategies? Any useful learning resources are also welcomed. Thanks a lot for sharing.
For clojurescript, shadow-cljs is usually the recommended way. It makes integration with the npm ecosystem (almost) transparent. - https://github.com/thheller/shadow-cljs - https://shadow-cljs.github.io/docs/UsersGuide.html - #shadow-cljs
@dromar56 Thanks for sharing. Shadow-cljs is indeed a fantastic tool for CLJS development and deployment. Do you use shadow-cljs with any other build tool for compiling CLJ, like into a uberjar, etc.?
shadow-cljs is cljs-only. For clojure the two options are either - lein (battery included, but falling more and more out of favor) - or deps.edn, the offficial tool (https://clojure.org/guides/deps_and_cli) I prefer deps.edn, but it's pretty barebone. Building a jar with lein is simple:
lein uberjar
With deps.edn, you need to use something like depstar (https://github.com/seancorfield/depstar)
Also interesting read if you want to use deps.edn: https://github.com/seancorfield/dot-clojureThanks a lot for helping. If you won't mind sharing, after you've got the frontend codes from shadow-cljs and the uberjar, how do you deploy to the web?
So you want to deploy both a backend (the uberjar) and front-end (shadow-cljs)?
An uberjar only needs a server with java installed, you upload the jar by any method and do java -jar uberjar-name.jar
.
For the frontend, it depends on your app:
- either it's served by the backend, in which case it would be already in the jar or somewhere in the same server
- it's only static files talking to your server API, in which case you can put them on a cdn, on a server behind nginx (or similar), etc...
Frankly, "deploy to the web" is very vague, can't help more than that
You should ask another question describing more precisely what you're trying to do. In another thread, because it's 11PM for me and I'm going to bed ๐
That's very helpful already. Really appreciate your help at this hour. Following the docs, I already have a working demo on development mode, but crossing the chasm from dev to prod is a bit vague to me since I am not familiar with how JVM deployment looks like. Good idea to start another thread later with more precise question. Have a good night! ๐
Anyone got this message when using deps.edn to include a git repo? Error building classpath. Destination path "<repo name>" already exists and is not an empty directory
Yes, that's a common error. I usually just rm -rf ~/.gitlibs
and try again, but apparently you can also try -Sthreads 1
on the command line. The developers think it might be contention between download threads.
Ah nice! Thanks. That was the directory I was looking for
I'm so happy right now ๐ within 3 day, I successfully : 1. installed DOOM emacs 2. at least know/pretty familiar with the navigation (key combinations) 3. Start REPL after some errors 4. Create a project & connect 2 ns inside 5. move on after stuck at ch 6 in http://braveclojure.com Thank you so much, for the support... I'll learn more, dig more
TFW people new to (doom-)emacs have a much nicer looking config than mine after 10 years of tweaks. But vanilla4ever
Or Prelude?
just install doom-themes
and/or doom-modeline
!
I am trying to connect my Clojure applications with an APM tool, that traces some variables and the execution time of functions in a nested way. So the HTTP call is the top span, then there are three SQL statements which are child spans, and so on. I created a function to wrap the calls Iโd like to trace, and itโs at least working, but I wonder what the best and most idiomatic way would be. My initial approach was to return both the result and a trace-event (a map containing all the info) from each function and collect and send the events in the end, but this feels rather clumsy. Also, if something in the process chain there is an exception, I will lose trace events. Another way could be to pass a โsend trace eventโ callback into the functions I want to trace, and invoke the callback from the inside. Which one would you prefer? Or are there other ways I am not thinking about?
a classic lispy approach is to make wrapper functions that have identical return value but also trace your info:
(defn wrap-trace
[f]
(fn [& args]
(some-tracer-pre f args)
(let [res (apply f args)]
(some-tracer-post f args res)
res)))
that way you never need to mix tracing code into your other logicso if you have foo
, you can call (wrap-trace foo)
to get a traced function with the same behavior
in some cases you might want (alter-var-root #'foo wrap-trace)
which replaces the root binding, but often you'd also want to attach the old value of foo to the var metadata (eg. think about what happens if you wrap a function that was already wrapped)
Then the first step was right, I have such a wrapper function. And it would be okay to invoke side effects in that wrapper? There would be no other way really, would it?
right, that's the only way to do it - I assume that at the root your tool requires some mutation or side effect to work
also, you mentioned exceptions - so you'd want to use try
around the let body, likely with a special cleanup call in the catch
Yes, itโs sending network requests.
Thanks for the answer, that helped! ๐
yeah - the cleanest way is if the individual usages of the API can remain idempotent, then the only side effect needed is the network request invoked from each wrapper, but you might end up needing client side coordination, in which case a thread plus a queue is probably simplest
That shouldnโt be a problem, it is the same request every time, with similar data, and there is already a java lib that handles all the calls non-blocking