beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
raspasov 2021-03-29T00:07:55.233800Z

@sova if you have the data ready in a vector, and it’s a lot of data, subvec might be worth it since will be constant time (i.e. faster than take/drop, etc)

raspasov 2021-03-29T00:08:27.234500Z

But for most UI cases, and if you have a few hunded items, etc; linear will most likely be good enough

2021-03-29T05:40:35.236Z

@sova highly dependent on context, but you could also partition the sequence into indexable blocks of fifty each and keep that in memory

👌 1
sova-soars-the-sora 2021-03-29T19:51:26.254200Z

(memoize ...) ? or some other way

2021-03-29T08:59:31.237900Z

What's the general go-to approach of handling errors? I have recently been writing a lot of go so my head is stuck in the return value, error way of doing things. The two things I can think of are: • just return nil (loses error context) • throw exception (loses nice control flow, easy ability to aggregate errors before reporting them, etc)

gon 2021-03-29T09:13:22.239800Z

Also a pattern used is [error-code-or-true/false related-value] exceptions are not very common

2021-03-29T09:13:40.240200Z

Not sure how idiomatic: You can return a map of (possibly) result, and (possibly) list-of-errors

2021-03-29T09:14:31.240600Z

(What gon says, but then a map instead of a tuple ^^)

2021-03-29T09:15:56.241Z

I'm happy to hear exceptions aren't that common

2021-03-29T09:16:19.241600Z

I don't mind returning a vec of errcode/value, I just don't want to transplant my recent go experience onto Clojure if there's a more idiomatic way

solf 2021-03-29T09:20:52.244Z

@anders152 As a data point, aws-api is often cited as a great lib. Here’s how it handles errors:

Barring client side exceptions, every operation on every service will return a map. If the operation is successful, the map will be in the shape described by (-> client aws/ops op :response). If AWS indicates failure with an HTTP status code >= 400, the map will include a :cognitect.anomalies/category key, so you can check for the absence/presence of that key to determine success/failure.
https://github.com/cognitect-labs/aws-api#responses-success-failure

1
🙌 1
rakyi 2021-03-29T09:21:35.244800Z

AFAIK both exceptions and values representing errors are idiomatic, depends on context when to use one or the other

Kenneth Gitere 2021-03-29T13:20:32.248700Z

What would you guys recommend as a good Clojure backend framework that also has support for websockets?

sova-soars-the-sora 2021-03-30T15:49:31.309500Z

Depending on how "real-time" it has to be, you might find success with ajax and REST endpoints and keeping track of "last-seen-timestamp" for each client on the server, so when you get a /what-is-up POST from an ajax (cljs) client you can simply send the delta of new events since :last-seen-timestamp. I'm using this approach in a social-ish network thing right now.

KJO 2021-03-29T13:25:31.248800Z

I’ve found Immutant and Pedestal to work perfectly well for me. Different approaches, but both have served me well. http://immutant.org/documentation/2.1.9/apidoc/guide-web.html#h3380 & https://github.com/pedestal/pedestal/tree/master/samples/jetty-web-sockets

KJO 2021-03-29T13:29:30.249Z

There’s also a slightly outdated blog post that might be helpful at https://heykieran.github.io/post/using-sse-and-websockets/

hindol 2021-03-29T13:29:49.249300Z

I have used Pedestal but it required quite a bit of setup. Ring with the Jetty9 adapter is far simpler for hobby projects. https://github.com/sunng87/ring-jetty9-adapter#websocket

hindol 2021-03-29T13:31:25.249700Z

Check this guide for more options: https://purelyfunctional.tv/mini-guide/clojure-web-servers/

Kenneth Gitere 2021-03-29T13:31:33.250Z

Thanks for these suggestions. I had seen Luminus after a simple Google search. Is it a suitable alternative?

hindol 2021-03-29T13:32:18.250300Z

I have not used Luminus myself. But everyone suggests that as a good beginner framework. Definitely worth trying.

Kenneth Gitere 2021-03-29T13:33:31.250500Z

Beginner friendly would be exactly what I need 😅

KJO 2021-03-29T13:36:49.250700Z

Yup, Luminus is a good option; it uses immutant as the web server, so you’ll be fine. Good luck.

Kenneth Gitere 2021-03-29T13:43:39.250900Z

I'm trying to make a turn based game server in Clojure so there's certainly going to be a lot of "fun" problems to solve

2021-03-29T15:35:39.251500Z

Hello !

2021-03-29T15:36:00.251600Z

I'm a hobbyist , learning clojure ..

2021-03-29T15:36:25.251700Z

Clojure is my first functional programming language ..I know a bit of python

2021-03-29T15:57:16.252700Z

Welcome! If you like map and filter and reduce of Python’s stdlib, or the entirety of functools or itertools you will feel right at home here ;)!

blak3mill3r 2021-03-29T16:25:53.253400Z

and if you like python's list comprehensions, you are going to love clojure's for /`doseq` macros

2021-03-29T22:35:37.257Z

(let [foo {:people [{:name "Bob" :id 1} {:name "Alice" :id 0} {:name "Eve" :id 2}]}
      current-name "Bob2"
      selected-id 1]
          
  
  )
How would I update the item in :people that has :id equal to selected-id to change the :name to current-name ? Is their a better way than find the item in :people, and update it, then remove the old item from people, add the new one and then reassoc that list to people?

2021-03-29T22:50:03.258400Z

i.e. like this

(let [db {:people [{:name "Bob" :id 1} {:name "Alice" :id 0} {:name "Eve" :id 2}]
          :current-name "Bob2"
          :selected-id 1}]
  (let [new-item (-> (filter #(= (:id %) (db :selected-id)) (:people db))
                      (first)
                      (assoc :name (db :current-name)))
        updated-people (-> (remove #(= (:id %) (db :selected-id)) (:people db))
                           (conj new-item))]
    (assoc db :people updated-people)
    ))
There must be a better way!

pavlosmelissinos 2021-03-29T22:53:50.259700Z

(let [foo {:people [{:name "Bob" :id 1} {:name "Alice" :id 0} {:name "Eve" :id 2}]}
      current-name "Bob2"
      selected-id 1]
  (->> (:people foo)
       (map (fn [m]
              (if (= (:id m) selected-id)
                (assoc m :name current-name)
                m)))
       (assoc foo :people)))
something like this? edit: else was missing and you want to have the full map in the end, fixed edit2: meh, unbalanced parens, now it's really fixed

blak3mill3r 2021-03-29T22:54:10.260200Z

there are a lot of ways... how about this with specter:

(let [db {:people [{:name "Bob" :id 1} {:name "Alice" :id 0} {:name "Eve" :id 2}]
          :current-name "Bob2"
          :selected-id 1}]
  (setval [:people ALL #(= (:id %) (:selected-id db)) :name] (:current-name db) db))

👍 1
2021-03-29T22:55:04.260600Z

oh nice! I've never used Spectre before. I'll look into it! That seems pretty slick

blak3mill3r 2021-03-29T22:56:19.261200Z

powerful, maybe a rather steep learning curve

blak3mill3r 2021-03-29T22:56:30.261500Z

but it's not too hard to get started with things like this

dpsutton 2021-03-29T22:56:34.261700Z

(let [update-if (fn [pred f] (fn [x] (if (pred x) (f x) x)))]
  (let [foo {:people [{:name "Bob" :id 1} {:name "Alice" :id 0} {:name "Eve" :id 2}]}
        current-name "Bob2"
        selected-id 1
        maybe-correct (update-if (comp #{selected-id} :id) #(assoc % :name current-name))]
    (update foo :people #(mapv maybe-correct %))))
{:people [{:name "Bob2", :id 1} {:name "Alice", :id 0} {:name "Eve", :id 2}]}

👍 1
dpsutton 2021-03-29T22:57:36.262600Z

with a bit more tasteful naming it could be quite nice. maybe-correct named apply-edit might make it a bit more clear. update-if could use a better name but i put it in a separate let as it feels very library-ish

2021-03-29T22:58:24.262800Z

Thanks! Yeah that's nicer than what I had.

2021-03-29T23:07:33.263300Z

I would do something like this

➕ 2
2021-03-29T23:12:49.263700Z

Yeah, i should definitely learn specter

raspasov 2021-03-29T23:36:14.264800Z

For updating deeply nested immutable data, Specter does it in a very concise and quite performant way

raspasov 2021-03-29T23:37:24.266100Z

One important note though: I always try to de-nest my data as much as possible; more often than not, you can use more shallow data structures which makes your life way easier;

raspasov 2021-03-29T23:37:58.266800Z

Specter can be super useful if you’re dealing with incoming data that you don’t have initial control over.

👀 1
raspasov 2021-03-29T23:38:32.267600Z

Say, you have some value, 10 levels deep in some JSON, and you need to just (inc some-value), while preserving the whole shape.

raspasov 2021-03-29T23:38:40.267800Z

Specter is the best for that.