@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)
But for most UI cases, and if you have a few hunded items, etc; linear will most likely be good enough
@sova highly dependent on context, but you could also partition the sequence into indexable blocks of fifty each and keep that in memory
(memoize ...)
? or some other way
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)
Also a pattern used is
[error-code-or-true/false related-value]
exceptions are not very common
Not sure how idiomatic: You can return a map of (possibly) result, and (possibly) list-of-errors
(What gon says, but then a map instead of a tuple ^^)
I'm happy to hear exceptions aren't that common
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
@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-failureAFAIK both exceptions and values representing errors are idiomatic, depends on context when to use one or the other
What would you guys recommend as a good Clojure backend framework that also has support for websockets?
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.
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
There’s also a slightly outdated blog post that might be helpful at https://heykieran.github.io/post/using-sse-and-websockets/
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
Check this guide for more options: https://purelyfunctional.tv/mini-guide/clojure-web-servers/
Thanks for these suggestions. I had seen Luminus after a simple Google search. Is it a suitable alternative?
I have not used Luminus myself. But everyone suggests that as a good beginner framework. Definitely worth trying.
Beginner friendly would be exactly what I need 😅
Yup, Luminus is a good option; it uses immutant as the web server, so you’ll be fine. Good luck.
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
Hello !
I'm a hobbyist , learning clojure ..
Clojure is my first functional programming language ..I know a bit of python
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 ;)!
and if you like python's list comprehensions, you are going to love clojure's for
/`doseq` macros
(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?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!(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 fixedthere 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))
oh nice! I've never used Spectre before. I'll look into it! That seems pretty slick
powerful, maybe a rather steep learning curve
but it's not too hard to get started with things like this
(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}]}
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
Thanks! Yeah that's nicer than what I had.
I would do something like this
Yeah, i should definitely learn specter
For updating deeply nested immutable data, Specter does it in a very concise and quite performant way
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;
Specter can be super useful if you’re dealing with incoming data that you don’t have initial control over.
Say, you have some value, 10 levels deep in some JSON, and you need to just (inc some-value), while preserving the whole shape.
Specter is the best for that.