This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-18
Channels
- # architecture (25)
- # beginners (57)
- # boot (3)
- # cider (38)
- # clara (6)
- # cljsrn (6)
- # clojure (54)
- # clojure-china (4)
- # clojure-greece (1)
- # clojure-italy (3)
- # clojure-romania (1)
- # clojure-russia (7)
- # clojure-spec (68)
- # clojure-uk (46)
- # clojurescript (73)
- # community-development (2)
- # core-async (7)
- # cursive (17)
- # datomic (143)
- # duct (2)
- # emacs (12)
- # events (5)
- # figwheel (3)
- # fulcro (15)
- # hoplon (19)
- # jobs (12)
- # jobs-discuss (85)
- # nginx (3)
- # off-topic (111)
- # onyx (7)
- # other-languages (1)
- # re-frame (30)
- # reagent (19)
- # remote-jobs (1)
- # ring (7)
- # rum (1)
- # shadow-cljs (18)
- # spacemacs (4)
- # specter (4)
- # sql (24)
- # test-check (1)
- # unrepl (10)
- # vim (6)
- # yada (1)
"9. It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures." -- http://www.cs.yale.edu/homes/perlis-alan/quotes.html
Aha, thanks! I was quoting that at someone the other day and I couldn’t remember where it came from, so I settled on “… said some lisper” ¯\(ツ)/¯
I use defmulti/defmethod a lot, but then I do lots of msg and data processing, so I'm a bit weird compared to others (I do very little web programming)
Please could you spare some RT LOVE for this Clojure UK story.. @conan and his crew!
@yogidevbear we use them quite a bit… maybe 50 defmulti
’s throughout our codebase, with a few hundred defmethod
s… Could be more or less but I have multiple branches of the same repos checked out
Morning
@rickmoynihan would you say that you have a general use case for them? (e.g. like the message routing stuff people have mentioned above or something completely different)
multiple dispatch 🙂
@yogidevbear Some examples might be more helpful 🙂
- The query language we use has three different query types so when you handle queries it’s useful to dispatch on each type. Sometimes depending on context the type might be a java object (for interop with 3rd party libraries) or a {:type :select}
map clojure side.
- In the ui you may have a concept of “panel” that can render dynamically based on some kind of :type
- In parts of our application we need to coerce input arguments, which might be tabular data/files etc, but might also have several source types so the dispatch key is composite i.e. [source-type destination-type]
. These are also organised in a hierarchy (and we do some fancy introspection on the defmulti
to also project some of this info back out as a JSON for API for another service to consume and build UI widgets from.
- We use integrant, so ig/init-key
multimethod etc are used to define components and start the app.
- I use them for multi-specs.
- Handling mine types and format types and various things related to content negotiation etc
There are also lots of places in our code base where I think we could improve things by using them more.
Sweet, that's a pretty broad list and sounds like a super interesting project
well technically it’s not one project 🙂
interesting work then 😉
Yes, it is. I can’t complain too much 🙂
>too much
haha, I’m not sure you can be a software developer and not complain a bit! 😉
complaining is often a pre-requisite to improving things
oh @yogidevbear i forgot about another thing we do - lots of our api requests get transformed into a [api-method-key params]
variant in the api layer, and that is dispatched against a multimethod, which returns a [response-key params]
variant, which is then xformed in to an http response. it makes http-related stuff very thin and generic, makes error handling a breeze, keeps model stuff out of http land, makes model stuff very easy to test (no request spoofing) and keeps http dependencies out of the model module
Yeah the variant pattern is pretty neat. I’ve been thinking about using it more.
variants work particularly well with promises and promise short-circuiting - our error handling boils down to (throw (pr/ex error-key error-args))
, which encodes the [error-key error-args]
variant into the promise error state, and somewhere up the promise chain (e.g. in the aforementioned http layer) something will do a pr/catch
, and unpack then present or encode the error
so I am making the mistake of mixing some java with my Clojure... and I have found Zach Tellman's virgil project to recompile my java... but as I use a port I can't seem to restart it easily... has anyone found a solution to this
afaics @thomas virgil is creating a new ClassLoader for each compilation https://github.com/ztellman/virgil/blob/master/src/virgil/compile.clj#L81 which would mean that your old versions are happily carrying on running, isolated under their old ClassLoader
I can close my port... but then when I add some java code I can't reopen it again for some reason.
presumably something isn't getting closed down... are you using a ServerSocket ?
ah - i haven't ever used that directly, although i presume netty uses it under the covers...
so to close it you get the ServerSocket from the ServerSocketChannel and close that ?
ah, no, there's an inherited close method
hmm. i was going to suggest you try SO_REUSEPORT, but it seems java doesn't support it
I actually don't use Netty... I though i'd copy the http-kit ideas over... use Java to create maps and call into my clj code.
aahh just re-read your comment... yes I think Netty uses that as well. I'll investigate it some more when I get some time for this... just a playing with a few ideas and see if they work.
why did you decide to write java for the ServerSocketChannel interop @thomas? (i tend to avoid it - i can only remember once where i had to do it)
I thought I'd use the same trick as http-kit... use a layer of Java to handle the low level network intricacies and then hop into clojure to do the fun bit where you can add (more) value.
that looks like a fun project
mqtt
is a great protocol
really well designed