Fork me on GitHub
#beginners
<
2022-12-06
>
Uli05:12:58

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?

George06:12:50

doesn't Figwheel work fine with any backend though?

George06:12:01

for example in my project I have backend Clojure and frontend with FIgwheel, but maybe I don't understand your situation

jumar16:12:10

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/3197https://github.com/bhauman/figwheel-main/blob/master/docs/docs/your_own_server.md#requirements-for-working-with-figwheel

Matthew Downey18:12:04

It'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.

Uli06:12:46

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

Michael12:12:49

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

Abhinav16:12:15

Highly recommend https://www.braveclojure.com/clojure-for-the-brave-and-true/ That’s how I learnt clojure :)

practicalli-johnny08:12:42

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

Mattias12:12:30

The inspiration (?) for the Rings of Power TV series: https://www.braveclojure.com/clojure-for-the-brave-and-true/

Ted Ciafardini17:12:39

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 be

dpsutton17:12:34

that’s pretty terse. but there’s (remove (some-fn :nice? :kind?) people)

👍 3
Ted Ciafardini17:12:18

Terse. Never used some-fn before. Thanks!

Matthew Downey18:12:06

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)

jumar20:12:43

Note that your code gets significantly shorter if you use https://clojure.org/guides/weird_characters#_anonymous_function

(remove #(or (:nice? %) (:kind? %)) people)

Abhi Saxena20:12:51

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

dpsutton20:12:26

can you write a function that takes a single map, checks the section title and if it is equal to B updates dataPresent?

Abhi Saxena20:12:02

Yes, but then I am not sure how to construct the original collection back

dpsutton20:12:25

if you can make that function and call it f, then (map f collection) would do what you want

Abhi Saxena20:12:35

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.......

Abhi Saxena20:12:02

the collection is huge in size

dpsutton20:12:21

ah, you only want to update a single record. not all of them are candidates for updating?

dpsutton20:12:29

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

dpsutton20:12:45

or you can use a vector, find the index of the one you want and then update just that index

sam20:12:23

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.

dpsutton20:12:37

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.

Abhi Saxena20:12:49

Is there a possibility I can filter that map, dissoc it , update it and add it back with conj

Abhi Saxena20:12:19

I am not sure what functions to use for that......

sam21:12:31

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.

sam21:12:58

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.

sam21:12:29

Actually, I think there may be a better way to do this using split-with

sam22:12:35

(let [[init [m & tail]] (split-with #(not= (get % "sectionTitle") "B")
                                      ms)]
    (concat init (cons (my-update-fn m) tail)))

sam22:12:57

I think that also avoids processing the rest of the elements after the correct map is found.

sam22:12:13

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.

Abhi Saxena22:12:18

Can't agree more, thanks much for all your help and guidance

skylize03:12:30

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"}]

🙌 1
dpsutton03:12:25

Zip map is not lazy. But it only proceeds for the items in the shortest sequence

skylize03:12:03

Ok. Can we just wrap the zipmap expression in lazy-seq then?

dpsutton03:12:56

Zip map returns a map. The clojure implementation does not have a lazy behavior. It will have defined keys and associated values

skylize03:12:26

... Well, map is lazy. So I guess replace the zipmap expression with

(map (fn [i x] [i x]) (range) coll)

sam03:12:46

update only works on associative collections (e.g. maps or vectors). You’d have to convert it to a vector first, right?

🤒 1
sam03:12:48

I think one of the premises of the question is that the data is in a list.

skylize05:12:59

Aah. So many gotchas on this problem.

skylize05:12:20

@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.

Abhi Saxena06:12:24

thanks @U11BV7MTK @UABEM258C @U90R0EPHA - I was finally able to solve this problem, without your help it wouldn't be possible.

sam14:12:28

@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.

skylize16:12:32

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.

mathpunk20:12:15

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))))

mathpunk20:12:29

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

mathpunk20:12:46

It really looks like the macroexpand-1 is correct to me

mathpunk20:12:55

but it might not be, I’m new at this

mathpunk20:12:16

so I can’t quite tell if this is an error in the library I’m using, or if I’m bad at macros

mathpunk20:12:25

the latter is highly likely

Bob B20:12:40

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>

mathpunk20:12:20

i was kind of weirded out by how namespaces and local bindings looked to work…. I don’t know enough to know why, it was just an intuitive, this smells funny

mathpunk20:12:34

adding that # and I’m up and running, thanks for the find!

👍 1