On 10 March 2025 03:55:21 GMT, Larry Garfield <[email protected]> wrote: >Support for nested blocks is absolutely mandatory, whatever else we do. If >you cannot nest one async block (scheduler instance, coroutine, whatever it >is) inside another, then basically no code can do anything async except the >top level framework. To stretch the analogy slightly, this is like saying that no Linux program could call fork() until containers were invented. That's quite obviously not true; in a system without containers, the forked process is tracked by the single global scheduler, and has a default relationship to its parent but also with other top-level processes. Nested blocks are necessary *if* we want automatic resource management around user-selected parts of the program - which is close to being a tautology. If we don't provide them, we just need a defined start and end of the scheduler - and Edmond's current suggestion is that that could be an automatic part of the process / thread lifecycle, and not visible to the user at all. >This function needs to be possible, and work anywhere, regardless of whether >there's an "open" async session 5 stack calls up. > >function par_map(iterable $it, callable $c) { > $result = []; > async { > foreach ($it as $val) { > $result[] = $c($val); > } > } >return $result; >} This looks to me like an example where you should not be creating an extra context/nursery/whatever. A generic building block like map() should generally not impose resource restrictions on the code it's working with. In fact as written there's no reason for this function to exist at all - if $c returns a Future, a normal array_map will return an array of Futures, and can be composed with await_all, await_any, etc as necessary. If an explicit nursery/context was required in order to use async features, you'd probably want instead to have a version of array_map which took one as an extra parameter, and passed it to along to the callback: function par_map(iterable $it, callable $c, AsyncContext $ctx) { $result = []; async { foreach ($it as $val) { $result[] = $c($val, $ctx); } } return $result; } This is pretty much just coloured functions, but with uglier syntax, since par_map itself isn't doing anything useful with the context, just passing along the one from an outer scope. An awful lot of functions would be like this; maybe FP experts would like it, authors of existing PHP code would absolutely hate it. The place I see nested async{} blocks *potentially* being useful is to have a handful of key "firewalls" in the application, where any accidentally orphaned coroutines can be automatically awaited before declaring a particular task "done". But Daniil is probably right to ask for concrete use cases, and I have not used enough existing async code (in PHP or any other language) to answer that confidently. Rowan Tommins [IMSoP]
