This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-12-06
Channels
- # adventofcode (71)
- # aleph (1)
- # announcements (6)
- # aws (1)
- # babashka (27)
- # beginners (60)
- # biff (7)
- # calva (3)
- # clj-kondo (3)
- # clj-yaml (1)
- # clojure (60)
- # clojure-europe (43)
- # clojure-nl (3)
- # clojure-norway (75)
- # clojurescript (16)
- # code-reviews (7)
- # css (4)
- # cursive (47)
- # datascript (4)
- # events (5)
- # fulcro (37)
- # gratitude (5)
- # hyperfiddle (4)
- # introduce-yourself (4)
- # joyride (23)
- # juxt (4)
- # malli (4)
- # membrane (64)
- # nbb (8)
- # off-topic (12)
- # other-languages (6)
- # pathom (6)
- # polylith (9)
- # random (3)
- # rdf (66)
- # reitit (3)
- # releases (2)
- # shadow-cljs (18)
- # tree-sitter (10)
Hi. Is there a way to circumvent cors policies in my dev-setup. How do you do it? Szenario: I'm writing a clojurescript-app and want to implement a persistence layer. For that I wanted to use opensearch (elasticsearch), so I started a opensearch container. Since the app is served by my dev-environment / figwheel and the container listens to another port I'm hitting the cors-border. My thoughts on it: I could write a little backend, which accessses opensearch, but then I'd lose my figwheel integration, because I would have to serve my javascript also from that backend. Do you have any ideas, how to keep local dev-env and avoid this cors-problem?
for example in my project I have backend Clojure and frontend with FIgwheel, but maybe I don't understand your situation
So you are serving your javascript app from one endpoint and accessing elasticsearch directly from the client running on another endpoint? If you want that you need to set https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS in your dev environment, e.g.
Access-Control-Allow-Origin: *
Here's something related to figwheel:
• https://clojureverse.org/t/how-to-add-a-cors-header-to-figwheel-server-for-cljs/3197
• https://github.com/bhauman/figwheel-main/blob/master/docs/docs/your_own_server.md#requirements-for-working-with-figwheelIt's a hack, but when I've hit this issue I just run https://github.com/Rob--W/cors-anywhere on localhost, and have the Clojurescript app route requests through localhost. Works fine if you distribute the app as a zip file with HTML and JS inside, and whoever is using it doesn't mind running the local cors proxy.
Thanks for the answers. Had no time so far to test it, but I'm gonna give it a hit these days. Thank you @UP7RM6935 @U06BE1L6T @UEN45M0KV
Hi, can anyone recommend a friendly material to learn clojure. Have being trying to learn this awesome language since last year but no inspiring materials. Thanks
someone shared this a few days ago https://clojurians.slack.com/archives/C8NUSGWG6/p1669983174224489
Highly recommend https://www.braveclojure.com/clojure-for-the-brave-and-true/ That’s how I learnt clojure :)
https://clojure.org/guides/learn/clojure covers the fundamentals of the language https://clojure.org/community/resources lists of community learning resources, including my own practical books at http://practical.li which also has free books and 100+ hours of Clojure coding videos I learned Clojure by solving https://4clojure.oxal.org/ challenges https://exercism.org/tracks/clojure has 84 challenges to solve in Clojure, with optional mentor support
The inspiration (?) for the Rings of Power TV series: https://www.braveclojure.com/clojure-for-the-brave-and-true/
Is there a more terse way to remove from a seq of maps based on the non-existence of keys? “All people who are not nice & not kind”
(remove (fn [person] (or (:nice? person) (:kind? person))) people)
I feel like there must beTerse. Never used some-fn before. Thanks!
There's also (comp (remove :nice?) (remove :kind?))
if you're using transducers / chaining with further computations, e.g.:
(sequence
(comp
(remove :nice?)
(remove :kind?)
(map something-else)
(comment "etc."))
people)
Note that your code gets significantly shorter if you use https://clojure.org/guides/weird_characters#_anonymous_function
(remove #(or (:nice? %) (:kind? %)) people)
Hi All, Give a list of Maps, how can we update the values only if the keys matches certain criteria, do we need to destruct and construct again ({sectionTitle A, dataPresent 1, dateCreated 08/05/2020} {sectionTitle B, dataPresent 0, dateCreated 10/05/2020} {sectionTitle C, dataPresent 2, dateCreated 10/05/2020}) I am looking for updating the dataPresent only when sectionTitle is B and the collection structure should remain the same
can you write a function that takes a single map, checks the section title and if it is equal to B updates dataPresent?
Yes, but then I am not sure how to construct the original collection back
if you can make that function and call it f
, then (map f collection)
would do what you want
I did that with map but I have been told since you are just updating a single value inside map why do you even need a map function.......
the collection is huge in size
ah, you only want to update a single record. not all of them are candidates for updating?
Correct
you don’t have a great data structure for editing in the middle. often you can take a list and turn it into a map by treating one of the keys as an index. so sectionTitle
would be your map
or you can use a vector, find the index of the one you want and then update just that index
But if you don’t know where in the collection the map you want to edit is ahead of time and if you’re going to ad-hoc construct a data structure only for this single purpose, you might as well just use map
after all, right? You’re going to have to iterate through the collection either way.
I think constructing a vector from a list would effectively involve iterating through the whole list, right? And in any case, the big-O complexity to find the right map is going to be linear.
yeah. the best answer is to have a datastructure that matches your access patterns. But for sure it doesn’t make sense to turn a sequence into a vector, update in O(1) time and then still just use it like a sequence. Because the cost to turn it into a vector is the same as just mapping. You really have to use the proper data structure in more places. Turning it into a convenient one in one place at linear cost doesn’t improve over modifying a structure in linear time.
Is there a possibility I can filter that map, dissoc it , update it and add it back with conj
I am not sure what functions to use for that......
Hm, maybe something like?
(loop [init '()
[m & tail] ms]
(if (= (get m "sectionTitle") "B")
(concat init (conj tail (my-update-fn m)))
(recur (conj init m) tail)))
I couldn’t think of a way to do it with standard lib fns, so resorted to a loop/recur. But I could be missing something.I think this does what you want in that it avoids iterating through the rest of the maps after it finds the one you want to update.
(let [[init [m & tail]] (split-with #(not= (get % "sectionTitle") "B")
ms)]
(concat init (cons (my-update-fn m) tail)))
I think that also avoids processing the rest of the elements after the correct map is found.
Hmm, scratch that, since split-with
is implemented as [(take-while pred coll) (drop-while pred coll)]
it will process the beginning of the list twice. So in the average case it won’t save you anything unless you think the map of interest will appear near the beginning of list most of the time. I suspect you’ll have to do something like what I did in my first solution (although I think my code can probably be improved) if you want to avoid processing the whole list.
But in any case, I guess if it were me I’d be thinking hard about whether the added code complexity is worth the performance optimization. This operation is going to be O(n) regardless.
Can't agree more, thanks much for all your help and guidance
zipmap
is effectively lazy, isn't it? And some
will short-circuit.
So we can zipmap
a range to the list to discover the index of the matching predicate with some
, and use that as the key to update
.
(defn update-first [pred transform coll]
(let [idx (some (fn [[i x]] (when (pred x) i)) (zipmap (range) coll))]
(if idx
(update coll idx transform)
coll)))
(let [m [{"sectionTitle" "A", "dataPresent" 1, "dateCreated" "08/05/2020"}
{"sectionTitle" "B", "dataPresent" 0, "dateCreated" "10/05/2020"}
{"sectionTitle" "C", "dataPresent" 2, "dateCreated" "10/05/2020"}]]
(update-first
#(= "B" (% "sectionTitle"))
#(update % "dataPresent" inc)
m))
; =>
[{"dataPresent" 1,
"dateCreated" "08/05/2020",
"sectionTitle" "A"}
{"dataPresent" 1,
"dateCreated" "10/05/2020",
"sectionTitle" "B"}
{"dataPresent" 2,
"dateCreated" "10/05/2020",
"sectionTitle" "C"}]
Zip map returns a map. The clojure implementation does not have a lazy behavior. It will have defined keys and associated values
... Well, map
is lazy. So I guess replace the zipmap expression with
(map (fn [i x] [i x]) (range) coll)
update
only works on associative collections (e.g. maps or vectors). You’d have to convert it to a vector first, right?
@UABEM258C How do you conclude that split-with
will process the start of the list twice? Looking at the source, that doesn't make sense to me.
thanks @U11BV7MTK @UABEM258C @U90R0EPHA - I was finally able to solve this problem, without your help it wouldn't be possible.
@U90R0EPHA well drop-while
and take-while
will both iterate across the maps until they find the one that fails the predicate, right? That’s all I meant. There are 2 separate passes. But, on the other hand, an algorithm that only does a single pass but does twice as many cpu operations per step wouldn’t be any better. These things are subtle. Benchmarking is probably a good idea if it is performance critical.
Oh. It just hit me. Yes. The call to drop-while
will start from the head and traverse until failed predicate, even though take-while
already located the split point.
I’m trying to write a macro to avoid boilerplate about the a db session (using gorillalabs/neo4j-clj).
;; what works
(with-open [session (db/get-session selected-db)]
(doall (users session)))
;; what I wrote
(defmacro query
[query-name]
`(with-open [session (db/get-session selected-db)]
(doall (~query-name session))))
what happens:
(macroexpand-1 '(query users))
;; => (clojure.core/with-open
;; [query-macros/session (db/get-session query-macros/selected-db)]
;; (clojure.core/doall (users query-macros/session)))
(macroexpand '(query users))
;; => Syntax error macroexpanding clojure.core/let at (notebooks/query_macros.clj:29:1).
;; query-macros/session - failed: simple-symbol? at: [:bindings :form :local-symbol] spec: :clojure.core.specs.alpha/local-name
;; query-macros/session - failed: vector? at: [:bindings :form :seq-destructure] spec: :clojure.core.specs.alpha/seq-binding-form
;; query-macros/session - failed: map? at: [:bindings :form :map-destructure] spec: :clojure.core.specs.alpha/map-bindings
;; query-macros/session - failed: map? at: [:bindings :form :map-destructure] spec: :clojure.core.specs.alpha/map-special-binding
so I can’t quite tell if this is an error in the library I’m using, or if I’m bad at macros
it looks like the symbol session
is being resolved to the current ns, which clojure doesn't like for a local binding - using a gensym might provide some progress... actually, the guide page seems to demo almost your exact use case as a candidate for gensym: <https://clojure.org/guides/weird_characters#gensym>