Table of Contents
In Kotlin while
and for
block, break
and continue
can be used, but they can’t be used in forEach
or repeat
block.
Environment
- Kotlin 1.3.11
First, I will introdyce easy coping strategy when we want to use break
or continue
in forEach
or repeat
.
Easy Coping Strategy
Both forEach
and repeat
can be replaced with for
. If we rewrite with for
, then we can use break
and continue
.
Before | After | |
---|---|---|
forEach |
something.forEach |
for (it in something) |
repeat |
repeat (time) |
for (it in time) |
Why break
or continue
can’t be used
(Directly speaking, Kotlin is built as it is.) while
and for
are completely different from forEach
and repeat
.
while
andfor
are syntax defined as Kotlin.forEach
andrepeat
are functions
They are very similar in writing, but while
and for
are syntax, in which break
and continue
can be used. On the other hand, forEach
and repeat
are higher order functions defined in Kotlin standard library.
1 2 3 |
releat (3) { // this is function } |
So, { ... }
is function for forEach
and repeat
.
It is weird that break
and continue
appear in function, isn’t it? break
and continue
can’t be used.
Another way to control iteration
To escape the block in higher-order functions such as forEach
and repeat
, use return
. It is natural that return
finish it, because it is a function.
But, using return
as it is, the caller function will be finished.
1 2 3 4 5 6 7 |
fun something() { listOf(1, 2, 3).forEach { println(it) return // finish something function } println("finish") } |
Use label to control it easily.
continue-like control
Using lambda
return@labelOfLambda
is continue
-like control in lambda.
1 2 3 4 5 6 7 8 |
fun something() { listOf(1, 2, 3).forEach { println(it) return@forEach // go back to the top of forEach block println(it) } println("finished") } |
The label can be named by ourselvs, such as labelName@{ ... }
.
If double forEach are used
If forEach
is used in double, name the label by yourself. In the following code, continue
works for outer forEach
loop.
1 2 3 4 5 6 7 8 9 10 |
fun something() { listOf(1, 2, 3).forEach outer@{ a -> listOf(4, 5, 6).forEach { b -> print(a) return@outer println(b) } } println("finished") } |
Using anonymous function
If you change lambda to anonymous function, you can simply use return
for continuation.
1 2 3 4 5 6 7 |
fun something() { listOf(1, 2, 3).forEach(fun(value: Int) { println(value) return // go back to the top of forEach block println(it) }) } |
break-like control
Use label, but you need outer scope function.
Using lambda
Surround with run
, and write return@run
.
1 2 3 4 5 6 7 8 9 10 |
fun something() { run { listOf(1, 2, 3).forEach { println(it) return@run // finish the loop println(it) } } println("finished") } |
As you can see, lambda is built without consideration of break
.
Using anonymous function
Use label like when we use lambda.
1 2 3 4 5 6 7 8 9 |
fun something() { var breakFlag = false listOf(1, 2, 3).forEach(fun(value) { println(value) return@run // finish the loop println(value) }); println("finished") } |
Summary of break and continue
break | continue | |
lambda | Scope function and label | label |
---|---|---|
anonymous function | return |