This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-03-29
Channels
- # announcements (8)
- # babashka (41)
- # beginners (45)
- # calva (23)
- # cider (17)
- # cljdoc (2)
- # cljfx (9)
- # clojure (40)
- # clojure-bay-area (13)
- # clojure-czech (4)
- # clojure-europe (46)
- # clojure-germany (6)
- # clojure-nl (13)
- # clojure-serbia (3)
- # clojure-uk (9)
- # clojurescript (76)
- # conjure (7)
- # cursive (5)
- # data-science (6)
- # deps-new (7)
- # fulcro (41)
- # graalvm (2)
- # jobs (6)
- # lsp (10)
- # malli (1)
- # mid-cities-meetup (1)
- # off-topic (77)
- # polylith (40)
- # re-frame (18)
- # releases (1)
- # remote-jobs (9)
- # reveal (1)
- # rewrite-clj (1)
- # shadow-cljs (11)
- # tools-deps (3)
- # tree-sitter (3)
- # vim (8)
- # xtdb (45)
@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 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?
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
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.
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))
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
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.