Kotlin 2.1 introduced non-local break
and continue
, a feature that enhances loop control in higher-order functions like forEach
. If you've ever struggled with nested loops or found yourself wishing for cleaner ways to exit or skip iterations in higher-order functions, this feature is here to save the day.
In this blog, we’ll dive deep into what this feature is, why it matters, and how you can use it effectively in your Kotlin projects.
Join our upcoming 6 Weeks Android Mentorship Program
What Are Non-Local break
and continue
?
When working with higher-order functions like forEach
, you might have noticed a limitation: there was no direct way to use break
or continue
. You had to rely on awkward workarounds, like adding return statements or using labeled loops.
With Kotlin 2.1, non-local break
and continue
allow you to:
Exit a loop (
break
)Skip an iteration (
continue
)
…directly from a higher-order function, just as you would in a regular loop!
This feature makes your code cleaner, more expressive, and easier to maintain.
Before Kotlin 2.1: The Android Struggle
Let’s say you’re iterating over a list of strings to filter valid user inputs:
val inputs = listOf("valid_input", "invalid", "valid_input_2", "stop_here")
inputs.forEach { input ->
if (input == "invalid") return@forEach // Skip invalid inputs
if (input == "stop_here") return // Exit the loop
Log.d("InputProcessing", "Processing: $input")
}
Log.d("InputProcessing", "Done!")
Here, return@forEach
skips invalid inputs, but to break the loop entirely, you need workarounds like returning from the enclosing function. This can make the code harder to read and maintain.
After Kotlin 2.1: Clean and Intuitive
With non-local break
and continue
, Android developers can now write clear and concise code:
val inputs = listOf("valid_input", "invalid", "valid_input_2", "stop_here")
inputs.forEach { input ->
if (input == "invalid") continue // Skip invalid inputs
if (input == "stop_here") break // Exit the loop
Log.d("InputProcessing", "Processing: $input")
}
Log.d("InputProcessing", "Done!")
Output
D/InputProcessing: Processing: valid_input
D/InputProcessing: Processing: valid_input_2
D/InputProcessing: Done!
How It Works
Non-Local continue
You can use continue
inside higher-order functions to skip the current iteration of the loop:
val words = listOf("apple", "banana", "cherry", "date")
words.forEach { word ->
if (word.startsWith("b")) continue
println(word)
}
Output
apple
cherry
date
Non-Local break
You can use break
to exit the loop entirely, even when using forEach
:
val words = listOf("apple", "banana", "cherry", "date")
words.forEach { word ->
if (word.startsWith("c")) break
println(word)
}
Output
apple
banana
Where Can You Use It?
Non-local break
and continue
work seamlessly in Kotlin 2.1 in all inline higher-order functions. This includes functions like:
forEach
map
filter
However, they cannot be used in non-inline functions, as these do not support the required inlining for non-local control flow.
Examples in Action
Let’s explore some practical use cases:
Example 1: Processing Files
Suppose you’re reading a list of filenames and want to stop at the first invalid file:
val files = listOf("file1.txt", "file2.txt", "invalid_file", "file3.txt")
files.forEach { file ->
if (file.contains("invalid")) break
println("Processing $file")
}
Output
Processing file1.txt
Processing file2.txt
Example 2: Skipping Specific Items
You’re iterating over a list of items, but you want to skip items that match a certain condition:
val numbers = listOf(10, 20, 30, 40, 50)
numbers.forEach { number ->
if (number % 20 == 0) continue
println(number)
}
Output
10
30
50
Example 3: Breaking Out of a Nested Loop
Non-local break
can be a lifesaver when working with nested loops:
val matrix = listOf(
listOf(1, 2, 3),
listOf(4, 5, 6),
listOf(7, 8, 9)
)
matrix.forEach { row ->
row.forEach { value ->
if (value == 5) break
println(value)
}
println("Finished row") // This won't print for rows after the break
}
Output
1
2
3
4
Finished row
Conclusion
Kotlin 2.1’s non-local break
and continue
simplify working with loops inside higher-order functions. Whether you’re iterating over collections or processing data, this feature makes your code more concise, intuitive, and readable.
If you haven’t already upgraded to Kotlin 2.1, now is the perfect time to do so and start leveraging these improvements.
Join our upcoming 6 Weeks Android Mentorship Program