zlacker

[return to "Rama on Clojure's terms, and the magic of continuation-passing style"]
1. moomin+eD[view] [source] 2024-10-14 10:17:59
>>nathan+(OP)
I feel like CPS is one of those tar pits smart developers fall into. It’s just a fundamentally unfriendly API, like mutexes. We saw this with node as well: eventually the language designers just sighed and added promises.

You’re better off with an asynchronous result stream, which is equivalent in power but much easier to reason about. C#’s got IAsyncEnumerable, I know that Rust is working on designing something similar. Even then, it can be hard to analyse the behaviour of multiple levels of asynchronous streams and passing pieces of information from the top level to the bottom level like a tag is a pain in the neck.

◧◩
2. oerste+xG[view] [source] 2024-10-14 10:48:48
>>moomin+eD
I agree. I'm sure that CPS has much more robust theoretical roots and that it's more general and powerful, but in practice it doesn't often look much different from classic callback-hell.

Generally, I prefer the coroutine/generator style, it is more explicit and straightforward syntax-wise. More importantly, it decouples operation execution from chaining. A function that emits multiple values in sync/async shouldn't be responsible for running the next function in the pipeline directly. It's better when the user of the interface has direct control over what function is run over which values and when, particularly for parallelizing pipelines.

I do understand that Rama builds such a syntax on top of CPS, and a compiler that implements generators has a similar execution model (perhaps an explicit state-machine rather than leveraging the function stack to do the same thing implicitly).

◧◩◪
3. pyrale+KT[view] [source] 2024-10-14 12:55:54
>>oerste+xG
That's because CPS is the callback hell.

Promises are a mechanism that was devised to separate the composition mechanism and the function itself, much like shell pipes exist to separate the control flow from the called function.

In this article, they implement a pipe-like mechanism, that avoids having to do "traditional" CPS. That is why they say the continuation is implicit. That being said, that mechanism goes further than that, and looks very much like Haskell's do-notation which enables programmers to use functional languages in an imperative style without knowing too much of the underlying implementation.

◧◩◪◨
4. nathan+V81[view] [source] 2024-10-14 14:44:46
>>pyrale+KT
The Cont monad in Haskell is only for single continuation targets and can't do branching/unification like Rama. That kind of behavior doesn't seem like it would express naturally or efficiently with just "do".
[go to top]