https://kotlinlang.org logo
#getting-started
Title
# getting-started
l

Landry Norris

04/19/2022, 3:25 PM
Is there an idiomatic way to write a while loop that checks some boolean condition, but also stops after some maximum number of loops? I have a loop that runs very often, but under rare conditions, it will run infinitely. In this case, I’m supposed to break from the loop after some number of iterations (250 in this case), regardless of whether the task the loop is trying to complete is completed. Right now, I’m creating a variable called i and incrementing it every iteration and adding i < 250 to the loop condition.
I figure it wouldn’t be too hard to make an extension function if this doesn’t exist, but I wonder if the stdlib has something like this.
c

Casey Brooks

04/19/2022, 3:51 PM
I don’t think there’s anything in the stdlib for running a loop like what you’re describing. I think that would lead to a pretty brittle code, not something that should be in the stdlib. If the loop is in a coroutine, then withTimeout might be a better way to handle this kind of use-case
l

Landry Norris

04/19/2022, 3:59 PM
Are there any performance implications of a coroutine using withTimeout? One place where I use this is in a function that should not take more than 15ms (ideally 10ms). Using withTimeout may be preferable to counting iterations if there’s not too much overhead associated with it.
y

Youssef Shoaib [MOD]

04/19/2022, 4:22 PM
You could do something with non-local returns like so:
Copy code
run containingScope@ {
    repeat(250){
        if(someCondition){
            return@outerScope Unit
        }
    }
}
l

Landry Norris

04/19/2022, 4:28 PM
I did something similar at one point. I think I refactored it since I wanted to make it more clear that someCondition was the primary condition and the loop counter was a secondary condition.
r

Ruckus

04/19/2022, 5:07 PM
Copy code
var tries = 0
while (someCondition && tries++ < 250) {
    ...
}
is probably what you already tried, but it seems like the most straight forward solution to me. Not sure why you'd want some other construct for it, unless I'm missing some context.
l

Landry Norris

04/19/2022, 5:13 PM
That's what I did at the end. It's clear on primary and secondary conditions. I just wanted to check if there was a clean stdlib way of doing this that doesn't add an extra tries variable. If not, I'll just stick with the tries method.
r

rocketraman

04/20/2022, 5:00 AM
@Landry Norris You could use a sequence. Example:
Copy code
generateSequence { task() }
  .takeWhile { someCondition }
  .take(250)
l

Landry Norris

04/20/2022, 4:47 PM
I didn't see that. I can see that being a good alternative. Thank you.
r

rocketraman

04/20/2022, 5:14 PM
Yes its actually quite nice and completely avoids the
var
. If the task is suspending, you use the same pattern with a flow builder e.g.
flow { emit(task()) }
.
2 Views