Open elizarov opened 1 year ago
Character (codegolf) economy seems to be not that big:
while (true)delay
repeatWithDelay
As opposed to repeat
, map
, fold
, or many other things, this doesn't seem to introduce a new level of abstraction with interesting guarantees that simplify understanding code at a glance (like map
promises to preserve the structure, repeat
guarantees that there are no funky mutable index manipulations, etc.), so I don't understand what would be gained.
Something would, however, be lost.
while (true)
is very malleable: you can add a break
if you want, or you can change the logic inside the while
to change the delay strategy to some of the other ones you're mentioning. When your code outlives newFunctionName
, you have to revert back to just a while (true)
again, you can't tweak it in-place. Or even worse, you still try to do so.while (true)
is universally understood, whereas any new abstraction has the cost of needing to be learned, along with its pitfalls: for example, unless the name is something completely self-evident like repeatWithFixedDelayBetweenInvocations
, just by looking at newFunction(2.seconds) { code() }
, it's not immediately clear that, if code()
that is usually supposed to be almost immediate suddenly took a whole second, the next invocation would be delayed.I never needed break
or anything like that. It typically runs until cancelled. My main gripe with while(true) { ... ; delay(...) }
block is that its intent is not clear upfront. Unless the code is clearly structured and the body inside the block is extracted into a separate function, I have to scan to the end of the loop to see that it does a fixed delay between iterations. That is what a clearly named function could solve.
Over time, I've found that I always have to write a helper function to make my code more readable, like this: https://github.com/elizarov/BGP-proxy/blob/main/src/commonMain/kotlin/BgpProxy.kt#L290-L295
It's also worth discussing whether the duration supplied is an interval (between the end of an execution and the start of the next) or a period (between the starts of successive operations). And if it's the latter is there a policy for long tasks to cancel the previous op to run the new one, run the new one ASAP, or skip until next scheduled time. Also if it's a period is the measure done with wall clock time (ignores CPU sleep) or CPU time (susceptible to sleep).
An interval is the obvious choice, but in that case I agree the while (true)
syntax is probably enough already. It's only the period case that starts to require non-trivial amount of code that one would want to abstract.
ScheduledExecutorService.scheduleWithFixedDelay
with the same semantics.schedule
is not coroutine-like ⇒withFixedDelay
.repeat
should be present in the name, since the function is repeat
-like ⇒ repeatWithFixedDelay
. fixed
is unnecessary ⇒ repeatWithDelay
.repeatWithDelay
still does not reflect that the code runs forever
(or untilCancelled
), but this should be conveyed with Nothing
return type. Related #1632
From the initial submission:
this simple pattern I've shown seems to be the most popular one that needs its own function
Here's a thought: what if this pattern is the most popular one because it is simple, when actually, people want fixed-period execution, but they figure that this loop is good enough for their (typically fast) actions? What are the specific use cases for fixed-quiescence execution?
The great thing about fixed delay between executions is that it is self-balancing under a load. The longer each operation takes, the longer period between calls becomes. It is not much useful for real-time stuff, like animations, but I'd say it is the approach of choice for any kind of "update this value periodically" type of application.
when actually, people want fixed-period execution, but they figure that this loop is good enough for their (typically fast) actions?
It actually happens to me.
Also note: setInterval
is very popular in JS.
So I'd like to have the over-engineered function that provides various ways to measure time and do a fixed-interval or fixed-period repetition
in coroutines library, possibly also with a parameter to behave in the fixed-delay manner. But to have a function just for that seems like a little overkill where while(true)
is enough.
While loop is also advantageous in that, besides break
, one can write (and immediately see) the delay
function either at the beginning, end of middle of the loop, or have multiple or even conditional delays.
Use case
I often see the following pattern in my own code and in the code other people write:
This reminds of the
repeat
function in the standard library that also server for the purpose of codifying the simple loop boilerplate. It looks that this should be a built-in function in the library.The Shape of the API
While it is clearly possible to over-engineer this function to provide various ways to measure time and do a fixed-interval or fixed-period repetitions, this simple pattern I've shown seems to be the most popular one that needs its own function. I've asked ChatGPT for potential names with this prompt: "Kotlin has repeat function that repeats a given operation a specified number of times. For coroutines, we need a function that repeats a given operation indefinitely often, but has a fixed delay between executions. List potential candidate names for such a function.". Here is the answer it produced:
Here are some potential names for the function:
repeatWithDelay
: This name reflects the fact that the function repeats an operation with a fixed delay between each execution.repeatForeverWithDelay
: This name highlights the fact that the function repeats an operation indefinitely, but with a fixed delay between each execution.repeatUntilCancelled
: This name suggests that the function will continue to repeat the operation until it is cancelled.loopWithDelay
: This name suggests that the function creates a loop that repeats the operation with a fixed delay.interval
: This name is borrowed from the setInterval function in JavaScript and suggests that the function repeats the operation at a fixed interval.steady
: This name suggests that the function creates a steady, repeating pattern with a fixed delay between each execution.tick
: This name is borrowed from the setInterval function in Python and suggests that the function repeats the operation at regular intervals like a ticking clock.heartbeat
: This name suggests that the function creates a regular, rhythmic pattern with a fixed delay between each execution.