3 ms·
I often see the claim that AE generalizes control flow, so you can (for example) implement coroutines. But the most obvious way I would implement AE in a langua
by duped 1y ago
I often see the claim that AE generalizes control flow, so you can (for example) implement coroutines. But the most obvious way I would implement AE in a language runtime is with coroutines, where effects are just syntactic sugar around yield/resume.
What am I missing?
- FjordWarden 1y agoYes, this is what Effect-TS is doing for JavaScript, minus the syntactic sugar, but I don't know if this is a good idea in the end. It reminds me of the Spring framework, DI is also a form of AE, but it spreads like cancer through the code. The other day I was watching this talk[1] from EffectDays on how to use effects on the frontend and the entire talk was a dude showing boilerplate that did nothing. I think that AE is a beguiling idea, it lets you express imperative code in a functional language, but in a language like JS the added work of wrapping everything in a function feel like a step down from writing the simples JS you can imagine. Just as a counter example, there is also canvasmotion[2] which also uses coroutines to express scenarios for 2D graphics and this feels like it is making something hard easier. [1] https://www.youtube.com/watch?v=G_jp87gxILE https://www.youtube.com/watch?v=G_jp87gxILE [2] https://motioncanvas.io/ https://motioncanvas.io/
- duped 1y agoI'm not sure I follow, JS doesn't have coroutines (generator functions can be used kind of like coroutines, but for example you can't resume them with an argument).
- FjordWarden 1y agoYes it does: function* greeter() { const name = yield "What's your name?" yield `Hello, ${name}!` } const gen = greeter() console.log(gen.next().value) console.log(gen.next("Alice").value)
- duped 1y agoTIL!
- herrington_d 1y agoOne thing AE provides but not coroutines is type safety. More concretely AE can specify what a function can do and cannot do lexically in code. A generator/coroutine cannot. For example, a function annotated with say `query_db(): User can Datebase` means the function can call database and the caller must provide a `Database` handler to call the `query_db`. The constraint of what can do and not is pretty popular in other programming fields, most notably, NextJS. A server component CANNOT use client feature and a client component CANNOt access server db.
- duped 1y agoCoroutines don't take away type safety any more than function calls do. But this gets back to what I was saying about generalization - the way I would implement what you're talking about is with coroutines and dynamic scoping. I'm still missing how AE is more general and not something you implement on top of other building blocks.
- LegionMammal978 1y agoI think the idea is that you can use it like async/await, except that a function must statically declare which interfaces it is allowed to await on, and the implementations are passed in through an implicit context. I'd be a bit worried that using it widely for capabilities, etc., would just multiply the number of function colors.
- codethief 1y ago> would just multiply the number of function colors. Would there really be colors? I mean sure, the caller of an effectful function will either have to handle the effect or become effectful itself, so in this sense effectfulness is infectious. However, while a function might use the `await` effect, when calling the function you could also just define the effect handler so as to block, instead of defering the task and jumping back to the event loop. In other words, wouldn't this solve the issue of colors? One would simply define all possibly blocking functions as await-effectful. Whether or not they actually await / run asynchronously would be up to the caller.
- LegionMammal978 1y agoOther people in this thread have claimed that AE handlers can resume the code multiple times, as in call/cc, as opposed to resuming a coroutine, which can only be done once for each time it yields. Personally, I don't see a whole lot of value in that, with how unpredictable execution could get. I'd rather write a function that explicitly returns another function to be called multiple times. (Or some equivalent, e.g., a function that returns an iterator.)