Fork me on GitHub

Interesting new proposal for concurrency primitives: — I’d love to hear some informed commentary from resident Clojure gurus 🙂


Thanks for sharing ! The problems described by the author are real, and were my primary motivation for writing


The approach is fundamentally different (FP) but design principles are the same : every forked process must eventually be joined, error propagation and cancellation support by default


Unfortunately I'm not that much into python to perform a deep comparison but this looks quite promising


I used to be deep into Python but lost the train to Python 3 so some syntax seems alien now…


IIUC, this nursery thing is sort of a lexical guarantee — processes spawned within that block are guaranteed to run to completion.


... So it's effectively fork-join?


Yes, but again, IIUC, by naming and passing around the “nursery” you can be sure that processes spawned from the top-level context will also be contained.


There’s also cancellation to factor in, which I think this library also tries to tackle…


yeah, I wish the author would drop the abstractions and just give a 1 paragraph description of what it is


I don't see much of a point to it. And the go statement itself was a massive lie. Lie as in, it was touted as "easy concurrency" like it brought some sort of solution to something when it was plain old forking. All it was, that it had shorter syntax than other systems, as far as semantics go, it's same thing as java's CompletableFuture only worse in pretty much every regard as is par for the course with Go.


I wouldn't go that far, it supports lightweight treading and in a way that supports dynamic extent. That's pretty rare on any runtime.


granted, I have intense dislike of Go in general


Why? I like to rag on the language as much as the next person, but for what it was designed to do, it does it pretty well.


Still likely to be the best language for serverless for miles around, right now. Still, what he's got here doesn't seem to account for the idea that it's not merely a fork, but a forked process that's intended to be somewhat autonomous. He's treating all go forks as if they're mere splits for convenient calculation - fork and join, sow and reap, no communication or coordination considered.


@U1YPTG4UF I don't see how his approach would be incompatible with communication/coordination. Basically what he says is that every logical process should have a parent, so that if something goes wrong sibling processes can be cancelled to free up resources and errors are always propagated somewhere. This doesn't prevent two sibling processes from sharing a common channel


Correct, but when the lifespan of the new process can span across an indefinitely long period, it makes it far less useful to enforce the join point for all these children processes.


If a process has indefinite lifespan, that means it's a top-level component of the application (e.g the http server, the DB connection pool), that is, its parent is the main process itself. You still want to shutdown these things properly before exiting if you get a sigterm or a critical error.


Not arguing that you don't need that; just that the improved utility of this abstraction seems to wane if you are using goroutines in that way, at least in comparison with other approaches.


scheme/lisp :: clojure = forth :: ??? Is there a forth that runs on the JVM, has nice java interop, and also compiles to js ?


“Factor is to Forth what Clojure is to Common Lisp” ^^


factor doesn't run on the jvm, though


if you really want jvm support, googling a bit just leads to some hoppy projects in various states of being umaintained


Ah, wait, “concatenative”, that’s the term I was trying to remember.


@qqq I think if you look up “concatenative clojure” you might have hits that are closer to what you’re looking for


@hiskennyness quick question about your comments on the flux challenge. Do you have a proposal on an alternative architecture for coordinating async sources?


@U0LJU20SJ That is a terrific, astute question. I confess I did not notice it myself until I decided to see how it handled Callback Hell, but my (and any) data flow package are perfect for absorbing async inputs, whether it be from XHR and a socket as with the Flux Challenge, or an interactive user choosing to click a button or press a key any time they choose. This is because the raison d’etre of dataflow is the accurate and reliable propagation of new state thru an existing DAG of state, so async sources are right in the wheelhouse, if you know your baseball. 🙂 Here is my write-up of that epiphany:


I just looked at that and it is a bit tl;dr. In the README on the JS solution I walk through a solid chunk of how it works, and that includes “oh, look, here is the XHR response!” and how dependent values are patiently waiting for it to arrive so they can work off it. I think that would be a better starting point, if you have not played with data flow packages like Javelin or JS MobX.


ps. Working on the CLJS version now.


it is quite an interesting view on the topic. I have never worked with Javelin nor Js MobX but I think I get a rough picture of what they try to achieve.


Interestingly enough I tried to tackle this problem myself and decided to tackle it in another way. I decided to combine - clojure async -> coordination of async operations - datascript -> data storage and expressive queries - reagent -> reactive data flow this turned out to be a fantastic match (for my use case at least) since I can express with queries/pulls the things that I want to display yet handle the asynchronous part separatedly and link all that reactively


it is not as declarative as I see in your examples but I think it is something like 80 - 90 % there 🙂


CLJS version almost done.


Yes, core.async is a natural for this. Did you see David Nolen’s video on using core.async to achieve some reactivity? It turned out well, tho it did require hand-wiring the pub-sub, if you will.


@hiskennyness unfortunately I have to leave this discussion for later since it is quite late at my timezone. Would be happy to continue it later


Declarative rocks. ReactJS gets my credit for turning everyone on to that.


I’ll be here. 🙂


I have seen some videos on core async but I dont remember any specific video on the topic. Can you send me a link?


Sure, I think I can find it. Catch you later.


oh yeah I remember this seminar. I read it though didnt know that there was a video


I dont particularly like the way that he develops that app though


there are just too many >! <! io operations


it becomes impossible to test


Yes, I also was struck by what I call “exposed wiring”. If you do the Flux Challenge with your approach I would be interested in seeing it.


The nice thing about data flow is that there is little need for testing. It decomposes complexity making every rule dead simple and easy to get right. If a rule works at all, it works. Really, data flow is as functional as it gets, and functional delivers QA all by itself.


Unfortunately I don't have the time to make the challenge right now. The approach that I mentioned is still not public and I try to keep it that way for the time being since I cannot promise support for it


However after looking at your cljs implementation I can say that my implementation is extremely similar. If you are curious you can check


Your feedback is very welcome 🙂