Reputation: 18484
How do I break out of a Kotlin repeat
loop?
(I see plenty of answers about forEach
, but I want to see a repeat
-specific answer.)
return
, because that will return from what contains the repeat
.break
, because:
repeat
is inside a loop, you'll break that looprepeat
is not in a loop, you'll get 'break' and 'continue' are only allowed inside a loop
These don't work (they are functionally identical):
repeat(5) { idx ->
println(">> $idx")
if(idx >= 2)
return@repeat // use implicit label
}
repeat(5) @foo{ idx ->
println(">> $idx")
if(idx >= 2)
return@foo // use explicit label
}
In both those cases, you get:
>> 0
>> 1
>> 2
>> 3
>> 4
(The return@
in both those blocks actually acts like a continue
, which you can see yourself if you add a println
after the if-block.)
So how can I break out of a repeat
?
Upvotes: 14
Views: 9379
Reputation: 23091
That seems like quite an abuse of the repeat
function. My understanding is that if you write repeat
, you intend it to repeat for that number of times. Any fewer is surprising.
For your example, I would use a for
loop:
for (idx in 0 until 20) {
println(">> $idx")
if (idx >= 2)
break
}
I think using the right tool is better than trying to coerce the wrong one (repeat
) to do what you want.
repeat
itself is implemented as a for
loop:
for (index in 0 until times) {
action(index)
}
Trying to use it for anything more than that and you may as well write your own version, rather than wrap up extra behaviour on top of it.
Upvotes: 10
Reputation: 18484
It turns out that repeat
(as well as forEach
) are not actually loops. They're higher-order functions, that is, they are functions that take functions as parameters.
(I find this frustrating: They look and act like loops, and feature prominently in the Kotlin docs. Why not just go all the way and promote them to proper loops in the language?)
To break out of a repeat
loop, this is the best answer I can devise:
run repeatBlock@ { // need to make a label outside of the repeat!
repeat(20) { idx ->
println(">> $idx")
if(idx >= 2)
return@repeatBlock
}
}
This is the result of that:
>> 0
>> 1
>> 2
I wish I could do it without introducing a new indent-level, but I don't think it's possible.
Upvotes: 14