
On Sun, 15 May 2022 at 23:00, Aaron Fink <aaronpfink@gmail.com> wrote:
Hello.
I've been thinking it would be nice to be able to use await to suspend execution until a condition is met (as represented by a function or lambda which returns a boolean.
Currently, as far as I can tell, the way to accomplish this is with a while loop which frequently checks the condition, suspending execution in between checks. My use case is in robotics, so I'll use that. Here's a minimal version of my current approach.
start_moving_to(dest) while distance_to(dest) > tolerance: await asyncio.sleep(1 / 60)
This requires choosing a somewhat arbitrary frequency with which to check the condition. But if the frequency is too high, the function may not be suspended often enough for other tasks to run and if it's too low, there's a significant delay before the condition's satisfaction can be noticed.
So here's my proposal for syntax that I think is quite a bit cleaner:
start_moving_to(dest) await lambda: distance_to(dest) <= tolerance
This eliminates the need to choose a frequency and makes the code even more readable.
But the frequency has to be defined somewhere. How does Python know when to check the function? Syntax doesn't remove that question, it only moves it around. What I would recommend is having your own "wait for condition" function that hides that logic away. Something like this (untested): POLL_FREQUENCY = 60 async def poll_until(pred): while not pred(): await asyncio.sleep(1 / POLL_FREQUENCY) Then, if you want to change your polling frequency, it's in one place, and not part of the logic of "are we theeeeere yet" which now only needs to concern itself with positions. A possibly-more-elegant solution might be to design your own event loop with an intrinsic frame rate, always advancing by precisely the same sleep interval and then checking whatever needs to be checked. But that would be a lot more work :) ChrisA