Discussion
Async Programming Is Just @Inject Time
hackingonempty: > If you want to read more, I’d recommend starting with the Effekt and Koka language toursInstead of exploring a research language that nobody uses you could try a mature effects system for a semi-popular language. I think Zio is great and runs on the JVM and ScalaJS. https://zio.dev/
rdevilla: > To start with, you need to remember that functions don’t exist. They’re made up. They’re a social construct.https://www.felixcloutier.com/x86/callSufficiently large distances of abstraction from the concrete, underlying mechanics are indistinguishable from religion and superstitious belief. Expect LLMs to widen this gap in understanding.We are not far away from the tech priests of the Adeptus Mechanicus.
noelwelsh: This article would benefit from an introduction that lays out the structure of what is to come. I'm expecting an article on effect systems, but it jumps straight into a chunky section on the implementation of function calls. I'm immediately wondering why this is here, and what is has to do with effect systems.Also, this is a very operational description: how it works. It's also to give a denotational description: what it means. Having both is very useful. I find that people tend to start with the operational and then move to the denotational.
gpderetta: > Your CPU doesn’t know or care what functions are [...]Well, most architectures do not use plain jumps with implicit arguments for function calls, but have explicit call/ret or branch-with-link instructions. Even those that used jumps had branch hints. The reason is that the microarchitecture must know about call/ret pairs to be able to predict the return path as the generic dynamic predictor is just not good enough for such a common path.Reduced prediction performance compared normal calls is actually a concern for some coroutine and async code.> in C we don’t have any dynamic lookup inside functions—every dynamic jump comes from an explicit conditional statementfunction pointers.
adamnew123456: > Well, most architectures do not use plain jumps with implicit arguments for function calls, but have explicit call/ret or branch-with-link instructions.Anyone who wants to go deeper on this would be well served doing some reading on "return oriented programming" and shadow stacks / control flow integrity. I got turned onto this by a few LWN articles that talk about the subject (https://lwn.net/Articles/940403/ among others).It turns out that "jump to this pointer" is actually a dangerous construct, and it's not something you get much high-level exposure to since functions as an abstraction are so unleaky.
jiehong: I heard ocaml had one?
jiehong: > having to add IO effects to all functionsSound like Haskell, and its Monads. I think it does end up being very similar in the end.Would you compare effects and monads?
yunnpp: I came here to ask the same question; did somebody just reinvent monads?Also note that much of Haskell now uses MonadIO, so you are no longer constrained to IO or having to manually lift IO into your monad, so long as your monad instances MonadIO. This makes code reuse across libraries trivial. I say this because their div() example says that it can only be called from an Exception effect context, which is like old-school IO-everywhere Haskell. It seems to me like they're going to run into the function colour problem.