What if your DSL could stop you from making hidden mistakes by itself?
Why DSL scope control with @DslMarker in Kotlin? - Purpose & Use Cases
Imagine you are building a complex recipe book app where you write nested instructions for cooking steps. Without clear boundaries, you might accidentally mix ingredients or steps from different recipes, causing confusion.
Manually keeping track of which part of the recipe you are editing is slow and error-prone. You might call the wrong function or access the wrong ingredient because the scopes overlap and the compiler can't warn you.
The @DslMarker annotation in Kotlin helps by marking DSL scopes clearly. It prevents accidental mixing of functions from different nested contexts, so you only access what belongs to the current scope. This keeps your code clean and safe.
fun recipe() {
cake {
flour()
frosting {
sugar()
flour() // Oops, flour from cake scope is accessible here
}
}
}import kotlin.DslMarker @DslMarker annotation class RecipeMarker class Cake { fun flour() {} fun frosting(block: Frosting.() -> Unit) { /*...*/ } } class Frosting { fun sugar() {} // flour() is not accessible here } @RecipeMarker fun cake(block: Cake.() -> Unit) { /*...*/ } // Now flour() inside frosting() is not accessible accidentally
It enables writing safe, readable, and well-structured DSLs where nested scopes do not interfere with each other.
When creating a UI layout DSL, @DslMarker ensures that properties of one layout container don't accidentally get mixed with another nested container, avoiding bugs in UI design.
Manual nested DSLs can cause confusing scope overlaps.
@DslMarker clearly separates DSL scopes to prevent mistakes.
This leads to safer and cleaner DSL code.