This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-07
Channels
- # announcements (5)
- # asami (17)
- # aws (11)
- # babashka (67)
- # beginners (90)
- # calva (13)
- # cider (17)
- # circleci (6)
- # clj-kondo (3)
- # clojure (53)
- # clojure-europe (12)
- # clojure-france (8)
- # clojure-germany (3)
- # clojure-losangeles (1)
- # clojure-nl (4)
- # clojure-norway (4)
- # clojure-spec (15)
- # clojure-uk (8)
- # clojurescript (41)
- # cursive (7)
- # data-science (6)
- # datomic (8)
- # emacs (10)
- # exercism (1)
- # figwheel-main (2)
- # fulcro (5)
- # graalvm-mobile (97)
- # graphql (1)
- # hyperfiddle (7)
- # inf-clojure (6)
- # interop (4)
- # introduce-yourself (5)
- # jobs (3)
- # kaocha (3)
- # malli (8)
- # meander (8)
- # music (3)
- # nrepl (7)
- # observability (1)
- # off-topic (45)
- # overtone (2)
- # polylith (63)
- # portal (2)
- # re-frame (26)
- # reveal (8)
- # ring (3)
- # shadow-cljs (56)
- # tools-build (5)
- # vim (11)
- # xtdb (8)
Is there a neat way to make cheshire
or clojure.data.json
gracefully ignore objects it cannot serialize (functions mostly)?
I have a large configuration map I want to persist to disk as json, but there's some functions sent along with it.
data.json uses a protocol for writing that dispatches on type so you could extend to the type you don't care about and then not write
If you overwrite the Object extension that covers the fall through case and that alone might be sufficient
If I have a key :test/mark
that can be at arbitrary depth and position and can appear multiple times inside a map, is there a way to target the map the key is inside and apply an update fn to it?
E.g with the map:
{:test/a [{:test/b {:test/mark :id
:test/other :val}}]
:test/z [{:test/different {:test/path [{:test/c {:test/mark :id
:test/other :val}}]}}]}
I would like to call an update fn on the map passing {:test/mark :id ...}
as the argument and replace it with the result without specifying both paths manually.
Is there a cljs-compatible library that implements a nice API for doing this or do I need to write it myself (presumably something tree recursive)?I solved it with https://github.com/redplanetlabs/specter and its recursive-path
macro:
(def MARKED-MAPS (sp/recursive-path [] p
(sp/cond-path vector?
[sp/ALL p]
#(and (map? %)
(not (contains? % :test/mark)))
[sp/MAP-VALS p]
:else sp/STAY)))
(sp/transform MARKED-MAPS (fn [_] {:tested true})
{:test/a [{:test/b {:test/mark :id
:test/other :val}}]
:test/z [{:test/different {:test/path [{:test/c {:test/mark :id
:test/other :val}}]}}]})
Inside :require
:
[com.rpl.specter :as sp :refer-macros [select recursive-path]]
How can I add clojure code into an existing spring boot app and repl into it while running it in eclipse
Does the spring boot auto config reload take eefect within nrepl session as well?
I'm sure this has been asked a million times, but what's the difference between (a :two)
and (:two a)
?
user=> (def a {:one "one" :two "two"})
#'user/a
user=> a
{:one "one", :two "two"}
user=> (a :three)
nil
user=> (a :two)
"two"
user=> (:two a)
"two"
You need to be careful with the (
versus {
. {:a :two}
and {:two :a}
are maps, the first with key a and value two, the second with key two and value a. But in your example you are using (a :two)
and (:two a)
(note (
vs {
. Keywords and maps are also functions that do the “obvious” thing. A keyword invoked as a function will look up the value associated to that key in an associative structure. A map used as a function will act as a function from key to value, or lookup the value of the key provided.
Prefer the keyword, as it handles nil
gracefully
(def a nil)
(:key a) ; => nil
(a :key) ; => NullPointerException
See also: https://github.com/bbatsov/clojure-style-guide#keywords-as-fn-to-get-map-valuesJust for completeness: Being able to use maps as functions is actually quite nice, and super obvious once you realise that a map is the prototype of a pure function. Keys in, values out. A “mapping” in the mathematical definition. (Rich also mentioned that in one of his talks)
hey hey, good clojurians,
how can I force a clojure hashmap
to become an arraymap
?
for reitit body response purposes
I am getting:
IllegalArgumentException: No implementation of method: :write-body-to-stream of protocol: #'ring.core.protocols/StreamableResponseBody found for class: clojure.lang.PersistentHashMap
ArrayMap seems to have nothing to do with this. What do you expect to happen when you return a hash-map as an HTTP body?
There are 2 ways to go about fixing this:
1. If you want to print the hash map as a string in the HTTP response, then return (str <your-map-here>)
2. If you have some way to stream hash-maps, you can do something like
(extend-protocol StreamableResponseBody
clojure.lang.PersistentHashMap
(write-body-to-stream [...] ...))
but array maps work fine
(muuntaja/format-response-middleware this middleware may be behind this magic?)
https://github.com/metosin/reitit/blob/master/examples/ring-swagger/src/example/server.clj#L66 you can see this example of an array map being used as the response body
Yes I don't think array-maps should be supported by default :thinking_face:, adding in a middleware which handles this makes more sense to me!
How can I turn my hashmap to arraymap so my middleware will work? 😄 I assume writing my own middleware can be avoided?
Do you have format-negotiate
middleware or exceptions added?
json should work out of the box with that middleware :thinking_face:
This definitely has nothing to do with hasmap or arraymap. You might confuse the fact that small maps in clojure are implemented by the ArrayMap class, and these get promoted to hashmaps as they grow.
Muntaaja automatically decodes returned values based on requests "Content-Type" headers
Maps are not valid Ring responses. You will need some middleware to encode the map to something like JSON or EDN or whatnot, for example Muuntaja as you write.
Check this for an example: https://github.com/metosin/muuntaja/blob/master/doc/With-Ring.md#simplest-thing-that-works
Well, I am using the same middleware. a request with a hashmap doesn’t work, arraymap does work
Very sure the error lies somewhere else
You can see that PersistentArrayMap
gets auto-promoted to PersistentHashMap
for more than 8 keys:
user=> (class (into (array-map) (zipmap (range) (range 8))))
clojure.lang.PersistentArrayMap
user=> (class (into (array-map) (zipmap (range) (range 9))))
clojure.lang.PersistentHashMap
It is merely an optimisation for very small maps. You should not need to care about these low-level details and just consider both persistent maps.ok, looks like you are right, it seems that my middleware probably fails because there is a nested list under that map
Thanks guys, I just switched over to jsonista for now and I gave up on the response coercion and response documenting features for now. I will get back to it eventually I guess.
If this is a problem of sorting the hasmap, why not use a sorted map instead?
@U9BQ06G6T , it is not, it is just me not using reitit and the middleware properly. Still haven’t gotten to understand whats going on there and how it should be used tho :)
I thought it was an ordering issue, as I have had that before, Array-maps tend to keep the order of insertions, but you can’t convert from one type to the other in a transparent way. Regarding reitit, I have never used it before 😄
I started using "1.11.0" version of Clojure but i am getting a lot of warnings about overshadowed vars (expected because of abs, update-keys, update-vals etc... ) is there anyway to hide these particular messages?
Where these warnings appear in library code I've created GitHub issues against the various projects: medley, java-time, zprint, lacinia, selmer...
Mostly the maintainers have already fixed the issues but not all of them have released new versions yet.
in the namespace that shadows, you can (:refer-clojure :exclude [abs whatever])
in the ns declaration
need to implement recursion without recursion over essentially as little state as possible
not sure if you’re aware but flatten
is already lazy. And its a pretty neat way to accomplish it with the general tree-seq
late follow up - it is recursion, a special kind where the recursive call is baked into a thunk
Hello, is there a function to unqualify a namespaced keyword? Something like:
(unnamespace :qualified/banana)
=> :banana
@UUA5X8NRL Q: why do you want to unqualify a keyword? Qualified keywords are idiomatic in Clojure -- and if you need to produce JSON, the various JSON libraries have options to remove the qualifier when producing JSON objects.
We use org.clojure/data.json
at work and it does that automatically:
dev=> (require '[clojure.data.json :as json])
nil
dev=> (json/write-str {:a/b 1 :b/c 2})
"{\"b\":1,\"c\":2}"
With Cheshire, you need to specify a :key-fn
:
dev=> (require '[cheshire.core :as cc])
nil
dev=> (cc/generate-string {:a/b 1 :b/c 2})
"{\"a/b\":1,\"b/c\":2}"
dev=> (cc/generate-string {:a/b 1 :b/c 2} {:key-fn name})
"{\"b\":1,\"c\":2}"
Not sure about any others.
(I recommend clojure.data.json
because it doesn't drag in the Jackson libraries which are notorious for both version conflicts and a number of well-known CVEs)
Aaron and myself are having the craziest problem our project is upgraded to 1.11.1 and the deps.edn + deps-graph tool reflect that much. we even deleted the .cpcache folder however.. every time we start clojure or clj, it will kick back to 1.10.3 (I removed every Clojure version from the .m2 folder that is older than 1.11.1 even)
i compared with a new project and using honeysql which has a clojure 1.9.0 dependency, but it will start 1.11.1 just fine.. very strange behavior!
we caught this while trying to upgrade our app https://github.com/naxels/youtube-channel-data to use (iteration from 1.11
This is the Clojar link to the dependency that pulls us back to 1.10.3: https://clojars.org/org.clojars.crowbrammer/csv-exporter and here’s the code: https://github.com/Crowbrammer/csv-exporter
The dependency is likely badly packaged, and includes the clojure class files in it's jar
that’s what we are starting to think as well, but is there any way to check for this in the JAR itself? I unzipped both csv-exporter and honeysql JAR files and found dependency for older Clojure in the pom files
It wouldn't be in the pom, like if you unzip the jar it it should spill out clojure class files like clojure.lang.RT
I wonder if the standard library or other popular libraries has a function that does this:
(pairwise [1 2 3]) ;=> ([1 2] [2 3])
have not been able to find it in the standard lib or medley.@U021UJJ3CQ6 - something you should be aware of with partition
(vs partition-all
). They behave differently when you don't enough elements:
user=> (partition 2 [1 2 3 4 5])
((1 2) (3 4))
user=> (partition-all 2 [1 2 3 4 5])
((1 2) (3 4) (5))
Thanks a lot @U05476190 I had seen this before but forgotten about it!
Hello. Trying to port a shell script. What should I do if I need to yield to interactive program/command?
if you use java.lang.ProcessBuilder and the inherit option for stdio, it just works
Clojure 1.10.1
(-> ["vim"]
(ProcessBuilder.)
(.inheritIO)
(.start)
(.waitFor))
0
what doesn't show up in that snippet is that it immediately launched vim
, and 0
was the vim exit codeone thing to be careful of - if you don't call waitFor
the repl and the sub-process will be trying to read the same content from stdin, with weird results
wait - I might have misunderstood what you need here - if you just need to exit early to the calling script, use (System/exit 0)