DSL scope control with @DslMarker in Kotlin - Time & Space Complexity
When using Kotlin's DSL scope control with @DslMarker, it's important to understand how the program runs as the input grows.
We want to know how the number of operations changes when we build nested DSL structures.
Analyze the time complexity of the following Kotlin DSL builder code.
@DslMarker
annotation class HtmlTagMarker
@HtmlTagMarker
class Html {
private val children = mutableListOf()
fun head(init: Head.() -> Unit) { children.add(Head().apply(init)) }
fun body(init: Body.() -> Unit) { children.add(Body().apply(init)) }
}
@HtmlTagMarker
class Head {
fun title(text: String) {}
}
@HtmlTagMarker
class Body {
fun p(text: String) {}
}
fun html(init: Html.() -> Unit): Html = Html().apply(init)
This code defines a simple HTML DSL with scope control using @DslMarker to avoid confusion in nested blocks.
Look for loops or repeated calls inside the DSL builders.
- Primary operation: Each nested block calls
apply(init)which runs the lambda passed to it. - How many times: The number of nested blocks determines how many times these lambdas run.
As you add more nested tags inside the DSL, each block runs its lambda once.
| Input Size (nested tags) | Approx. Operations |
|---|---|
| 10 | About 10 lambdas executed |
| 100 | About 100 lambdas executed |
| 1000 | About 1000 lambdas executed |
Pattern observation: The work grows roughly in direct proportion to the number of nested blocks you create.
Time Complexity: O(n)
This means the time to build the DSL grows linearly with the number of nested blocks.
[X] Wrong: "Using @DslMarker adds extra loops or slows down the DSL building significantly."
[OK] Correct: @DslMarker only affects how the compiler checks scope, it does not add runtime loops or extra operations.
Understanding how DSL scope control affects execution helps you write clear and efficient Kotlin DSLs, a useful skill in many Kotlin projects.
"What if we added recursion inside the DSL builders? How would the time complexity change?"