Ahhh, I see. (I'm not exactly sure of what a pom is, but) I got it working with your advice to include metal-{core,format} (instead of metal) thanks ❤️
pom
(and bom
) artifacts on Maven mean: "I am a list of artifacts" (rather than "I am an artifact"). Some systems know how to take a pom
(or bom
) and figure out the list of things to fetch automatically. Unfortunately for use, neither Leiningen nor the CLI/`tools.deps.alpha` know how, so we have to do it manually.
If you go look at the URL I posted (http://search.maven.org with the version and pom
), you'll see it shows a big ol' XML file and the relevant part is
<modules>
<module>core</module>
<module>formats</module>
</modules>
so that tells me there will be -core
and -formats
variants of the artifact that I should be able to download instead.
Thanks! That explanation helps a lot.
Is it possible to access RuntimeMXBean
, more specifically http://Is%20it%20possible%20to%20access%20RuntimeMXBean,%20more%20specifically%20(getUptime())[https://docs.oracle.com/javase/7/docs/api/java/lang/management/RuntimeMXBean.html#getUptime()] ? In my namespace, do I need to require something to access ManagementFactory
?
you'll need to import the class, and yes should be no problem to do
I’ve been getting by with the core library… this is a whole new world! Thanks!
user=> (import java.lang.management.ManagementFactory)
java.lang.management.ManagementFactory
user=> (.getUptime (ManagementFactory/getRuntimeMXBean))
75162
Any way to automatically reload assets on file save when using deps.edn
?
@signup867 I would advise against any sort of automated file reloader and just develop a really good, tight REPL-focused workflow where you evaluate every change as you make it. Watch Stu Halloway's talks on REPL-Driven Development and Running With Scissors; watch Eric Normand's excellent online course about REPL-Driven Development.
I have been doing Clojure in production for a decade now and I don't use watchers or auto-loading: I just eval every change I make, often without even saving files, I run tests from my editor, I develop into a live, running server process all the time, with my REPL active for days, sometimes even weeks.
where in the clojure doc is the explanation of the full syntax of argument lists. I know about stand-alone &
, but recently I've seen &env
and &something-else
which I can't remember.
I thought this might be in the documentation for fn
, but I didn't find it there
are you thinking about &env
and &form
? https://clojure.org/reference/macros#_special_variables
yes, are those variables, or are they syntax for the lambda list of a macro?
yes, are those variables, or are they syntax for the lambda list of a macro?
however the page you reference doesn't seem to show any examples or other information about how to use those special variables.
Hi all, trying to work out the best way to install a deps.edn project into my local maven. Currently my process seems like a huge hack but I haven't been able to find much on the process.
• generate the pom from the deps.edn with clj -Spom
• manually edit the pom, updating the version, group and artifact ids.
• run mvn install
Seems a bit round-about and I'm hoping I'm missing something obvious.
A couple of more specific questions:
• Is there some dep that will do this for me, I found uberdeps and depstar but they both still seem to expect a pom.xml to exist, so at that point I might as well use mvn I suppose.
• Is there a way to get the pom generated by clj -Spom
to fill out the version, group + artifact id, based on something I can write into the deps.edn itself
they are "magic" args available in any defmacro (in reality, defmacro actually generates a function that takes arity + 2 to pass these). the &env tells you the local bindings in scope when the form is expanded and &form is the actual form being expanded.
user=> (defmacro lookie [x] (println "&form" &form) (println "&env" &env) x)
#'user/lookie
user=> (let [a 100] (lookie 10))
&form (lookie 10)
&env {a #object[clojure.lang.Compiler$LocalBinding 0x749f539e clojure.lang.Compiler$LocalBinding@749f539e]}
notice that the vals of the &env map are actually Compiler$LocalBinding objects out of the internals of the compiler
@alexmiller Do I recall seeing the &env in the argument list of the macro somewhere? or is it only useful in the body of the macro?
only in the body (it is actually passed as an arg to the macro but that's not visible to you as a macro writer)
hi everyone, I have a namespaced map that I need to split into 2 separate maps for customer
and address
. I know I can destructure, however the address namespace has about a dozen things in it so Im wondering is there a quick way to extract keys from the same namespace.
{:customer/id 1 :customer/name "" :address/street "..." :address/city "..."}
Is there more syntax for the lambda list other than just variable names followed by & and a single trailing variable name?
as I recall there is something about default values. right?
you can use any destructuring syntax in the arg list
yes right.
does destructuring have any default value syntax?
it does for maps, with :or
ahhhh.. Where is the documentation for that?
reference is https://clojure.org/reference/special_forms#binding-forms
(defmacro foo [{:keys [a b] :or {a 1 b 2}}] ... )
or if you're using kw-arg style passing, you can destructure the variable arg seq:
(defmacro foo [& {:keys [a b] :or {a 1 b 2}] ...)
that's only for macros or also for normal functions?
yes!
I notice (fn [x & rest :as all] ...)
triggers an error, but (fn [[x & rest :as all]] ...)`` does not
(let [{:customer/keys [id name] :address/keys [street city]} your-map] ...)
the :as is not supported in the fn args
but it apparently is within the [[]] of a fn args
curious.
the fn is the exception here, can't say I know the reason why off the top of my head
every place else that has sequential destructuring does support it
not sure if that's just a historical quirk or if there's actually a reason for it
I'm writing a function what wants to provide arglists with the same syntax as fn. To implement this distinction will be tricky.
as its a recursive function. It'll have to know whether it is the top level recursion or not. guess not so tricky, but good do know.
In common lisp, destructuring is only allowed in macro lambda lists, not in normal functions. So that's a feature of clojure that I really appreciate.
yes, I know I could do this. However, this gives me id
name
street
city
that I have to use to construct my new maps customer
& address
. I have many keys in the address
namespace and would have to type them out twice (once to destructure and once to build new map). Is there a way to group them by namespace automatically from the map so I can save me some typing? Thank you!
don't think so - might depend a bit on what you're doing in between the destructuring and re-building
I'm just trying to transform the result of a sql query to this form (expected by a lacinia
graphql resolver)
{:id "" :name "" :address {:street "" :city ""}}
If so, do you just want to filter on key namespace?
(defn filter-key-ns [m key-ns]
(->> m
(filter (fn [[k v]]
(= key-ns (namespace k))))
(into {})))
(let [data {:customer/id 1 :customer/name "Alice"
:address/street "Jane Street" :address/city "New York"}]
(filter-key-ns data "customer"))
;; => #:customer{:id 1, :name "Alice"}
(defn filter-key-ns-2 [m key-ns]
(->> m
(filter (fn [[k v]]
(= key-ns (namespace k))))
(map (fn [[k v]]
[(keyword (name k)) v]))
(into {})))
(let [data {:customer/id 1 :customer/name "Alice"
:address/street "Jane Street" :address/city "New York"}]
(merge (filter-key-ns-2 data "customer")
{:address (filter-key-ns-2 data "address")}))
;; => {:id 1, :name "Alice", :address {:street "Jane Street", :city "New York"}}
yes this is what i wanted. thank you!
Glad it helped!
What are some easy and simple options for GUI programming with Clojure. I was looking at seesaw, but it says it is compatible with 1.5, and doesn't mention any of the newer Clojure versions so I am not sure if it will work. If not, any recommendations?
Check out CLJFX (and the #cljfx channel)
seesaw should work just fine with newer Clojure (and Java) versions
javafx (cljfx) is probably the more popular option these days though
I am an experienced network engineer that wants to learn Clojure as my first language, What website should I use to learn to code in Clojure?
Check out http://braveclojure.com
Also http://purelyfunctional.tv if you like video tutorials
I recommend using the websites that make sense to you most, everyone learns differently. I publish a free book and run a video series via YouTube. https://practicalli.github.io/ I do recommend using http://4Clojure.com to practice using the Clojure core functions. Keeping motivation is important when learning, so building something you find useful in Clojure will help.
Thank you. I will give those 3 websites a try for a few hours.
I just ran into this syntax in Hiccup (in reagent):
[:> ImportedReactComponent ]
I haven't seen this before, and, I couldn't find anything online in the Hiccup docs about it. Can someone point me to some documentation that discusses it?Hi all, how Unauthorizedaccessexception can be thrown in clojure? thanks
No need! I just found it in the reagent
docs. I was looking in the wrong place 🙂
ahh, I have found what I needed! https://clojure.org/reference/deps_and_cli#_local_maven_install had been misread the end of this thinking it still required a pom file
I take it back, I can build a jar seemingly quite easily, but the mvn-install thing seems to corrupt it
ahhh, what I didn't realise is that clj -Spom
doesn't override the existing version/group/artifact ids, so I only have to set them once! All sorted
Is there a way to escape commas from a string (csv)? Related but the answers are quite old: https://stackoverflow.com/questions/16215169/clojure-csv-with-escaped-comma
you shouldn't escape commas - you should quote the entry. the higher-voted answer there has a link to the "spec" (as much as it is), which is what the org.clojure/data.csv library follows (the only Clojure csv parser I use regularly)
$ clj -Sdeps '{:deps {org.clojure/data.csv {:mvn/version "1.0.0"}}}'
Clojure 1.10.1
user=> (require '[clojure.data.csv :as csv])
nil
user=> (csv/read-csv "\"a,b\",c")
(["a,b" "c"])
Got it. Will try that. I'm trying to follow the guide at https://andersmurphy.com/2019/01/06/clojure-sending-emails-with-sendgrid.html
However, if the data
is like:
[{:id 1, :t_id "1311350232249065472", :text "6b/ Substack: \"We've just been growing fairly consistently, and gradually the how-do-we-keep-up anxiety got bigger and bigger until there wasn't time left in the day to worry about whether we had product-market fit.\" – @cjgbest", :created_at "2020-10-01T12:17:34.611062000-00:00"}]
The resultant csv creates new column for every comma word between the commas (2nd row)yep, use a real csv library
for example https://github.com/clojure/data.csv
Yup, checking it out.
Re the \"
before We've
- I would usually expect that to be escaped with a double quote instead ""We've
and from a glance at the data.csv code that's what it's expecting too
but csv is notoriously non-standardized
Hmm, the data from the db itself has \"
[{:id 1, :t_id "1311350232249065472", :text "6b/ Substack: \"We've just been growing fairly consistently, and gradually the how-do-we-keep-up anxiety got bigger and bigger until there wasn't time left in the day to worry about whether we had product-market fit.\" – @cjgbest", :created_at "2020-10-01T12:17:34.611062000-00:00"}]
How should I go about turning this into a valid csv structure/string?yeah, you have to deal with the data you have
if I had to go out on a limb, I suspect you're not going to see that \" other than this case, so you could str/replace that with "", have no idea how often that would go wrong but might be a useful hack
I'll try that.
How did you write that csv?
I would say the code generating that csv is not correctly escaping quotes, so if you are generating the csv you should fix that code
it sounds like that's data from someone else
hell is other people's data right?
The linked to blog post includes code for naively creating csvs without any escaping
Which is why I suggested data.csv
But you will need to generate the csv using data.csv, not the obviously incorrect code in that blog post
Is there a pithy or builtin way to assign a key to a map if that key isn't already set? specifically when using the thread operators?
I have
(-> map
(assoc :key (get map key default-value))
But was curious if there is something better(merge defaults-map your-map)
(-> {} (update :key (fnil identity "new-value")))
merge
is better if its top level. good call
ooo @dpsutton, that might be it too
I guess merge could work too. it is top level Merge doesn't seem to work well in threading, or am I missing something?
then that is preferable imo
for the merge while using the thread operator, wouldn't I need to do something like
(-> map
(#(merge defaults-map %))
Or am I wrong?or are you thinking of just doing the merge after all of the threading is complete?
you should not contort things just for the threading macro
Usually I add my defaults upfront, then thread my operations subsequently
(-> (merge map defaults) ...)
That makes sense. I have an map (from a db) that's getting a bunch of transformations applied. At the end, some validation logic runs over it. and this key needs to exist, either using what was already there or add in the default value if not. and the whole block is already threaded
so I was hoping to slip in a 1-liner in the threading without changing too much more. thanks for the help!
The data stored in the db is as <the screenshot>. When reading that data using Toucan, I get the vector of maps as shared before: It looks like the following in the REPL:
[{:id 1, :t_id "1311350232249065472", :text "6b/ Substack: \"We've just been growing fairly consistently, and gradually the how-do-we-keep-up anxiety got bigger and bigger until there wasn't time left in the day to worry about whether we had product-market fit.\" – @cjgbest", :created_at "2020-10-01T12:17:34.611062000-00:00"}]
Notice the \"
is already present there.
Now, I need help with converting that to CSV.cc:// @alexmiller
I heard somewhere (can’t remember if it was a podcast, or article, or something else) about a daily problem/challenge to solve in Clojure. Does this ring a bell for anyone?
you are confusing yourself
the \" is escaping the " for reading in clojure
it is not present, what is present is a single "
The closest I can think of is http://www.4clojure.com/
(->> map
(merge defaults-map))
Or if you have a whole pipeline of ->
stuff but want a merge of defaults somewhere in the middle:
(-> stuff
(do-things)
(->> (merge defaults-map))
(do-more :things))
yes! this is exactly what I was trying to recall. thanks
(but, in general, it's considered somewhat bad practice to mix ->
and ->>
in a pipeline -- it generally indicates you're trying to do too much at once and potentially mixing data types, since sequence functions take the sequence last but collection and "object" functions take that argument first)
user=> (def data [{:id 1, :t_id "1311350232249065472", :text "6b/ Substack: \"We've just been growing fairly consistently, and gradually the how-do-we-keep-up anxiety got bigger and bigger until there wasn't time left in the day to worry about whether we had product-market fit.\" – @cjgbest", :created_at "2020-10-01T12:17:34.611062000-00:00"}])
#'user/data
user=> (let [baos (java.io.ByteArrayOutputStream.) w (java.io.OutputStreamWriter. baos)] (write-csv w [[(:text (first data))]]) (.flush w) (String. (.toByteArray baos)))
"\"6b/ Substack: \"\"We've just been growing fairly consistently, and gradually the how-do-we-keep-up anxiety got bigger and bigger until there wasn't time left in the day to worry about whether we had product-market fit.\"\" – @cjgbest\"\n"
user=> (read-csv (let [baos (java.io.ByteArrayOutputStream.) w (java.io.OutputStreamWriter. baos)] (write-csv w [[(:text (first data))]]) (.flush w) (String. (.toByteArray baos))))
(["6b/ Substack: \"We've just been growing fairly consistently, and gradually the how-do-we-keep-up anxiety got bigger and bigger until there wasn't time left in the day to worry about whether we had product-market fit.\" – @cjgbest"])
user=>
you can see when correctly encoded the " is a double " (which is not what you have) which is why read-csv throws an error
if you want to print something without escaping for reading you can use println
user=> (def s "\"")
#'user/s
user=> s
"\""
user=> (println s)
"
nil
user=>
Hmm, understood the quotes issue. Thank you.
There a few good coding challenges websites https://practicalli.github.io/clojure/coding-challenges/ 4clojure is excellent for learning the core functions in Clojure, it sometimes challenges you to rewrite them (at least in part)
> if I had to go out on a limb, I suspect you're not going to see that \" other than this case, so you could str/replace that with "", have no idea how often that would go wrong but might be a useful hack
The replacing hack also worked btw.
Modified the escape-csv-value
function to test and it does work.
(defn escape-csv-value [value]
(-> (str/replace value #"\"" "")
(as-> rdt (str "\"" rdt "\""))))
ha, that is great. forcing me to rewrite my code such that it really does fir exactly into the blank is a challenge unto itself