3 ms·
Zig's async manages the coroutines intrusively: It generates the state machine type, you provide the memory for where an instance of one runs, and you manage re
by kprotty 3y ago
Zig's async manages the coroutines intrusively: It generates the state machine type, you provide the memory for where an instance of one runs, and you manage resuming it until completion. Similar to Rust's Futures, it's pretty unopinionated in how you manage them so it works everywhere (i.e. freestanding). Could you clarify (or provide more reading on) how the other systems like delimited continuations, algebraic effects, and monads differ from Zig async + how they could be adapted in a similarly unopinionated/low-level way?
- chriswarbo 3y ago> Could you clarify (or provide more reading on) how the other systems like delimited continuations, algebraic effects, and monads differ from Zig async + how they could be adapted in a similarly unopinionated/low-level way? The key requirement for all these is an ability/API to defer and resume execution (indeed, delimited continuations are sometimes described as "resumable exceptions"). In higher-level languages we'd just assume the presence of first-class functions/closures, and use those to describe these features. I'm less familiar with how that looks in a very low-level language like Zig, however these "async frames" appear (to my naïve eyes) to be analagous; hence why I'm interested whether one of those more-general primitives could be provided instead (the answer might be no!). As for clarification on those features, here's a quick attempt. Firstly, note that all of these approaches are basically APIs to construct, consume, and combine (deferred) computations: they are unopinionated on how those computations get run (e.g. the user could supply a "main loop", or whatever). Delimited continuations are like exceptions, except the stack (AKA continuation) is passed to the handler, which may choose to resume it. We can implement coroutines/async/yield/etc. by having handlers which put their continuation in a queue and pop off some other one to resume instead; we can get data parallelism by resuming a continuation many times; we can get backtracking by remembering old continuations and trying them again; we can get parsers, probabilistic programming, nondeterminism, etc. https://en.wikipedia.org/wiki/Delimited_continuation https://en.wikipedia.org/wiki/Delimited_continuation Algebraic effects are similar, but defunctionalised: i.e. they represent control flow with datatypes, and are "interpreted" by a user-specified function. Applicative is an API for combining two computations concurrently, e.g. the product of Foo and Bar is a single computation yielding a pair of results. Monad can likewise combine sequentially, where Bar depends on the result of Foo. These feel more abstract, but are equivalent to the above e.g. see https://okmij.org/ftp/continuations/implementations.html https://okmij.org/ftp/continuations/implementations.html https://reasonablypolymorphic.com/#understanding-freer-monads https://reasonablypolymorphic.com/#understanding-freer-monad...
- anonymoushn 3y agoI think you can implement delimited continuations in terms of async frames and memcpy (like in Lua you can implement call/cc in terms of the built-in coroutine library plus coroutine.clone). The language doesn't guarantee that this works though if you try to resume an async frame somewhere other than its original address.
- chriswarbo 3y agoMore reading BTW: - 'Yield: Mainstream Delimited Continuations' builds them up by generalising for/yield (rather than try/throw), but the result is the same: https://www.researchgate.net/publication/228584945_Yield_Mainstream_Delimited_Continuations https://www.researchgate.net/publication/228584945_Yield_Mai... - 'A Poor Mans Concurrency Monad' seems to be the origin of async/await pattern (according to https://softwareengineering.stackexchange.com/a/377514/112115 https://softwareengineering.stackexchange.com/a/377514/11211... ), which is defined as a monad (technically a monad transformer) https://www.cambridge.org/core/journals/journal-of-functional-programming/article/poor-mans-concurrency-monad/A369E310ADAE4455020C918FC1D47958 https://www.cambridge.org/core/journals/journal-of-functiona... Incidentally, monad transformers are an attempt to work-around a deficiency of monads: that they don't compose. Algebraic effects have become popular precisely because they do compose.