Fork me on GitHub

anyone knows what is with immutant? Jim Crossley committed to it last on 20th of July, and its like 1.5 month noone is working on immutant.


@dbushenko not familiar with immutant in particular, but in clojure-land, a project not being worked on, often means that it's done, or at least no open bugs.


deciding whether to use immutant is also easy: do you need or want to integrate with a JEE or JBoss environment? => use immutant Otherwise, you might be better off piecing together various agnostic libraries: pedestal, ring, liberator, ... and run them on whatever server you like


I've got an idea that I would like to discuss with someone that will help people to learn new things and get more contributions to open source.


Who would be the best person to talk to?

Tom H.12:09:31

Why must it be some*one*? 🙂


If it’s Clojure-specific, I’d post it here and ask people to use “Start A Thread” to reply. If it’s not Clojure-specific I’d take it to the #off-topic channel


@dbushenko what @bendlas said 🙂 we'll fix bugs as they're reported, of course.


when defining assert-tag, is it better to do (assert-tag object keyword) or (asset-tag keyword object) ?


Are you expecting your function to mostly be used in a thread-first or thread-last pattern?


Is it working on single entities, or sequences of entities? I seem to recall the former are generally thread first (asset-tag object keyword), but if you would expect object to be a vector that could be mapped over or similar that's normally thread last (asset-tag keyword object) when called


I don't use the rest of immutant, but immutant.web is a nice way to run ring apps


What do people typically use for running background jobs inside of a Clojure web application? In a past life, I was doing lots of web development with Scala and Play and using Akka for background jobs. With Clojure and Ring, what’s a good choice for firing off the occasional background job?


ScheduledThreadPoolExecutor comes with the vm, but there are handy wrappers like At-At if you need it


there’s also Pulsar if you need to get fancy (eg. distributed state among many servers)


Hello everybody


I'm new at clojure and functional programming, I hope to learn a lot to get the better of it


welcome @rcustodio ! may I suggest joining the #beginners room? there are a lot of useful people in there


Thanks @ghadi!! I will go there


To ask questions


Good luck on the journey. Clojure is a fun time


@joelkuiper @noisesmith Thanks for the suggestions, I’ll start with those!


What's the go-to lib to process data (e.g. http post request) through a pipeline of validations, enrichment, error handling without deep branching and scattering try-catch, updating db and emitting events? The pipeline being the main thing. It doesn't need to be distributed, just expressed well.


Maybe something like pedestal interceptors?




@sundarj Doesn't seem like what I'm looking for. I want to define steps and if something fails I wanna know the step and context. Stuff like that.


Jokes aside, are you sure monads are the thing to recommend @sundarj ? It seems to me that unless you are interested in the FP aspects, they won’t be a very pragmatic way for someone to “pipeline processing steps”


well, no more pragmatic than -> and functions


i'm sure Haskellers would have something to say to you about that 😛


what he's asking for is a way to abstract away transforming data and errors into the same operations - that is exactly what category theory does


true, true


but there isn’t much of a practical benefit in this specific case over throwing exceptions


i would say not having to sprinkle try catch everywhere is a practical benefit


we already have nil punning in clojure to abstract away most null checks, this is more of the same


@sundarj out of curiosity, do you use monads on a regular basis in your Clojure code?


@U5ZAJ15P0 i'll pm you so as to not clog up this thread 🙂


aspiring (not much good) Haskell-er here: I thought the heavy category-theoretic stuff like Monad is too rigid - a pros if you're after type safety and predictability but a cons in dynamic world. But sounds like you want explicit control over the pipeline so this might be legit


@yonatanel one approach is following interpreter pattern. if you have functions return instructions that will be evaluated later, any function in the middle of the pipeline can override what the final list of instructions should be


you can also model as a stack machine


if you want side-effects, the pedestal interceptor model or any eager pipeline is a bad approach IMO - if you delay side-effects to the end you can have better commit/rollback, pruning unneeded side-effects, etc


I'm not aware of any library for this but in general, not hard to do. you can, e.g. exploit delay to decouple the functions that emit the instructions from the one that evaluates them


Agreed, this sort of stuff can easily be modeled via a set of "step" functions that are transformations from a state to a new state. If your state is immutable, rollback is free. Bonus points if (like interceptors) the steps are defined via data. Then everything is introspect-able, and you can even compose steps programmatically via other functions.


All that stuff becomes much harder once you hide it all behind opaque functions.


(as monads do)


just one note: rollback isn't necessarily free (what you're doing might not be commutative), but at least you can control rollback w/ something better than try/catch


yeah, although something like the state monad doesn't help with that either


e.g. your function can return [(forward-fn) (rollback-fn)]


Unless you use something like an IO monad, and doing that is just madness


@hcarvalhoaves or perhaps a record + a protocol with an optional IRollback


One of the reasons Interceptors use protocols is that once you need more than just (.invoke ...) functions become hard to use

Garrett Hopper21:09:04

Has anyone had issue with boot-reload trying to reload a file before boot-cljs has had time to write it to resources and be read to be served by your http server? (Aleph in my case; serving using ring.middleware.resource/wrap-resource)