You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Which functions should we expose, and what should they be called? #3
Discard vs send-on-channel can be the same function by taking an optional channel argument (as run_on_each already does).
run_on_each could also take optional task_status; if used with start(), it would internally create a channel pair and make start() return the receive end.
For fn+iterable versus iterable-of-fns, I think the split you have here makes sense. In practice, people are going to use this with either "a handful of things" or "an unknown large number of things". The "handful" case is much more likely to be running different functions and to not care about getting the results incrementally. It's easy enough to adapt between the two conventions: run_all([partial(fn, arg) for arg in args]) or run_on_each(lambda fn: fn(), fns).
(fun fact: for maximum inscrutability points, that run_all could also be run_all(map(partial(partial, fn), args)))
So I think the three we have now are a good three to be working with. Friendly amendment: maybe run_all can support being invoked with positional *args, so you can say run_all(thunk, thunk, thunk) instead of needing another pair of delimiters. I think the case where all the functions are listed in the code will be pretty common. Could also support both conventions, under the theory that callable iterables are rare.
Naming:
run_all is my favorite name of the three, it's very clear and Trio-ish, and it seems obvious to me that it takes a bunch of thunks and returns a list. asyncio calls this gather but I don't think that's as good of a name.
run_on_each also seems clear. I don't love that it parallels run_all but has a different result convention, but I can live with that.
amap is a little inscrutable compared to the other two, and I look at it and expect something that returns a list (probably due to too much exposure to builtin map in 2.x returning a list). We could borrow asyncio's terminology and call it as_completed, maybe? Or running_on_each or some other gerund-y form to emphasize the context manager aspect.
IIUC what run_all does but as an async iterator. I don't want to have to wait until all the functions have completed before I can pass the results off to the next step in the pipeline.
Activity
oremanj commentedon Sep 3, 2020
Hmm.
run_all([partial(fn, arg) for arg in args])orrun_on_each(lambda fn: fn(), fns).(fun fact: for maximum inscrutability points, that
run_allcould also berun_all(map(partial(partial, fn), args)))So I think the three we have now are a good three to be working with. Friendly amendment: maybe
run_allcan support being invoked with positional*args, so you can sayrun_all(thunk, thunk, thunk)instead of needing another pair of delimiters. I think the case where all the functions are listed in the code will be pretty common. Could also support both conventions, under the theory that callable iterables are rare.Naming:
run_allis my favorite name of the three, it's very clear and Trio-ish, and it seems obvious to me that it takes a bunch of thunks and returns a list. asyncio calls thisgatherbut I don't think that's as good of a name.run_on_eachalso seems clear. I don't love that it parallelsrun_allbut has a different result convention, but I can live with that.amapis a little inscrutable compared to the other two, and I look at it and expect something that returns a list (probably due to too much exposure to builtinmapin 2.x returning a list). We could borrow asyncio's terminology and call itas_completed, maybe? Orrunning_on_eachor some other gerund-y form to emphasize the context manager aspect.dhirschfeld commentedon Sep 3, 2020
I'll put in a plug for an async
as_completedfunction: groove-x/trio-util#7IIUC what
run_alldoes but as an async iterator. I don't want to have to wait until all the functions have completed before I can pass the results off to the next step in the pipeline.