In Kotlin, I cannot do a break
or continue
within a function loop and my lambda -- like I can from a normal for
loop. For example, this does not work:
(1..5).forEach {
continue@forEach // not allowed, nor break@forEach
}
There are old documentation that mentions this being available but it appears it was never implemented. What is the best way to get the same behavior when I want to continue
or break
from within the lambda?
Note: this question is intentionally written and answered by the author (Self-Answered Questions), so that the idiomatic answers to commonly asked Kotlin topics are present in SO. Also to clarify some really old answers written for alphas of Kotlin that are not accurate for current-day Kotlin.
There are other options other than what you are asking for that provide similar functionality. For example:
You can avoid processing some values using
filter
: (like acontinue
)You can stop a functional loop by using
takeWhile
: (like abreak
)A more complex, although nonsensical example where you want to do some processing, skip some resulting values, and then stop at a set of different conditions, would be:
A combination of these functions tends to eliminate the need for
continue
orbreak
. And there are endless different options here and more than can be documented. To get an idea of what can be done, it is best if you learn all of the functions available in the Kotlin standard library for collections, lazy sequences, and iterable.Sometimes there are cases where you have mutating state that still needs to
break
orcontinue
and is hard to do in a functional model. You can make it work using more complex functions likefold
andreduce
combined with thefilter
andtakeWhile
functions but sometimes that is harder to grok. Therefore if you really want that exact behavior you can use return from lambda expression which mimics acontinue
orbreak
depending on your usage.Here is a an example mimicking
continue
:And you can go more complicated and use labels when you having nesting or confusing situations:
If you want to do a
break
you need something outside the loop that you can return from, here we will use therun()
function to help us:Instead of
run()
it could belet()
orapply()
or anything naturally you have surrounding theforEach
that is a place you want to break from. But you will also skip the code within the same block following theforEach
so be careful.These are inlined functions so really they do not really add overhead.
Read the Kotlin reference docs for Returns and Jumps for all the special cases including for anonymous functions.
Here is a unit test proving this all works:
forEach
with break can be specificly substituted with any function:Or possibly even shorter:
If there's a need to use
continue
orbreak
, it is not ideal to useforEach
compare to normalfor-loop
If you really like to chain your command, and perform like a for-loop, use the normal functional chain, instead of
forLoop
E.g. for
Use
map
as for-loop,filterNot
as continue, andasSequence() & first
for breaktakeWhile stdlib function may be used instead of break.
For example,