86. The concept of lazy evaluation in Kotlin
Lazy evaluation is a programming concept where a value is not computed until it is actually needed.
In Kotlin, this is implemented using the lazy delegate — a powerful and simple way to defer initialization of a property until it's first accessed.
Syntax: lazy
val myValue: String by lazy {
println("Computed!")
"Hello from Lazy"
}
Output Example
fun main() {
println("Before access")
println(myValue) // Triggers computation
println(myValue) // Uses cached value
}
Output:
Before access
Computed!
Hello from Lazy
Hello from Lazy
Common Use Cases
Use Case | Why Use lazy? |
---|---|
Expensive computation | Delay until needed |
Optional initialization | Avoid null checks |
UI components | Avoid unnecessary inflation/setup |
Dependency loading | Defer until accessed |
87. What is a closure in Kotlin?
A closure in Kotlin is a function that captures variables from its surrounding scope — even after that scope has exited. This allows the function to remember and access those variables later.
Closure = Lambda/function + captured environment
Example of a Closure in Kotlin
fun counter(): () -> Int {
var count = 0
return {
count += 1
count
}
}
val increment = counter()
println(increment()) // 1
println(increment()) // 2
println(increment()) // 3
Another Example: Closure with Filtering
fun makeFilter(limit: Int): (Int) -> Boolean {
return { it > limit }
}
val filter = makeFilter(10)
println(filter(5)) // false
println(filter(15)) // true
The lambda closes over limit.
88. Closure vs Lambda
Here's a clear comparison table showing the difference between Closures and Lambdas, particularly in Kotlin (and also applicable in general programming):
Feature | Lambda | Closure |
---|---|---|
Definition | A function literal (anonymous function) | A lambda/function that captures variables from its outer scope |
Captures outer variables? | ❌ Not necessarily | ✅ Yes — that's what defines a closure |
Is every closure a lambda? | ❌ No (can be named function too) | ✅ Every lambda that captures state is a closure |
Is every lambda a closure? | ❌ Only if it accesses outer scope | ✅ If it uses/captures outer variables |
Can be assigned to variable? | ✅ Yes | ✅ Yes (if it's a function object) |
Example (Kotlin) | val greet = { println("Hello") } | var name = "Alex"; val sayName = { println(name) } (captures name) |
Retains state? | ❌ No state unless it's a closure | ✅ Yes — retains captured variables' state |
Use case | Lightweight, stateless function | When you need to keep using outer/local values in a lambda |
89. The concept of the until keyword in Kotlin
In Kotlin, until is a range function used to create a range of values that is exclusive of the upper bound.
Syntax
start until end
This creates a range from start up to but not including end.
Equivalent to: start..(end - 1)
Example
for (i in 1 until 5) {
println(i)
}
Output:
1
2
3
4
As you can see, 5 is not included.
When to Use until
- Avoiding off-by-one errors when working with ranges.
- Looping over indices of a list or array (excluding lastIndex + 1):
val list = listOf("a", "b", "c")
for (i in 0 until list.size) {
println(list[i])
}
90. until vs .. in table with example
Here's a clear comparison between Kotlin's .. and until operators using a table, along with examples:
Feature | .. (Range To) | until (Exclusive Range) |
---|---|---|
Meaning | Includes the end value | Excludes the end value |
Syntax | start..end | start until end |
Includes last number? | ✅ Yes | ❌ No |
Use case | When you want to include the upper bound | When you want to exclude the upper bound |
Type | IntRange, CharRange, etc. | IntRange under the hood |
Examples:
Using ..
for (i in 1..5) {
print("$i ")
}
Output: 1 2 3 4 5
Includes 5
Using until
for (i in 1 until 5) {
print("$i ")
}
Output: 1 2 3 4
Excludes 5
Important :
Expression | Includes end? | Example | Iterates Over |
---|---|---|---|
1..5 | ✅ Yes | for (i in 1..5) | 1 2 3 4 5 |
1 until 5 | ❌ No | for (i in 1 until 5) | 1 2 3 4 |