0
0
Kotlinprogramming~20 mins

DSL scope control with @DslMarker in Kotlin - Practice Problems & Coding Challenges

Choose your learning style9 modes available
Challenge - 5 Problems
🎖️
DSL Scope Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
Predict Output
intermediate
2:00remaining
What is the output of this Kotlin DSL code with @DslMarker?

Consider this Kotlin DSL code using @DslMarker to control scope. What will be printed when running buildHtml()?

Kotlin
import kotlin.text.StringBuilder

@DslMarker
annotation class HtmlTagMarker

@HtmlTagMarker
class Html {
    private val children = mutableListOf<Any>()
    fun body(init: Body.() -> Unit) {
        val body = Body()
        body.init()
        children.add(body)
    }
    override fun toString() = children.joinToString(separator = "\n")
}

@HtmlTagMarker
class Body {
    private val children = mutableListOf<String>()
    fun p(text: String) {
        children.add("<p>$text</p>")
    }
    override fun toString() = children.joinToString(separator = "\n")
}

fun buildHtml(): String {
    val html = Html()
    html.body {
        p("Hello")
        // The following line would cause a compile error if uncommented:
        // this@Html.body { p("World") }
    }
    return html.toString()
}

fun main() {
    println(buildHtml())
}
A<p>Hello</p>
B<body><p>Hello</p></body>
CHello
D<html><body><p>Hello</p></body></html>
Attempts:
2 left
💡 Hint

Look at how toString() is implemented for Html and Body. The Html class collects Body objects, and Body collects paragraph strings.

🧠 Conceptual
intermediate
1:30remaining
What is the main purpose of the @DslMarker annotation in Kotlin DSLs?

Why do Kotlin DSL authors use the @DslMarker annotation on their DSL marker annotations?

ATo prevent implicit receivers from different DSL scopes from being accessed simultaneously, avoiding scope ambiguity.
BTo automatically generate builder classes for the DSL elements.
CTo enable multi-threading support in DSL builders.
DTo allow DSL functions to be called without parentheses.
Attempts:
2 left
💡 Hint

Think about how nested DSL blocks might have multiple receivers with similar function names.

🔧 Debug
advanced
2:00remaining
Why does this Kotlin DSL code cause a compile error related to @DslMarker?

Examine the code below. Why does the call to p("World") inside the nested body cause a compile error?

Kotlin
import kotlin.text.StringBuilder

@DslMarker
annotation class HtmlTagMarker

@HtmlTagMarker
class Html {
    fun body(init: Body.() -> Unit) {
        val body = Body()
        body.init()
    }
}

@HtmlTagMarker
class Body {
    fun p(text: String) {}
    fun body(init: Body.() -> Unit) {}
}

fun main() {
    val html = Html()
    html.body {
        p("Hello")
        body {
            p("World") // Compile error here
        }
    }
}
ABecause the Body class does not implement the p function correctly.
BBecause @DslMarker prevents accessing the outer Html receiver's body function inside the nested body block.
CBecause nested body calls are not allowed in Kotlin DSLs.
DBecause the p function is private and cannot be accessed.
Attempts:
2 left
💡 Hint

Consider how @DslMarker restricts implicit receivers in nested DSL scopes.

📝 Syntax
advanced
1:30remaining
Which option correctly applies @DslMarker to create a DSL marker annotation?

Choose the correct Kotlin code snippet that defines a DSL marker annotation named MyDslMarker and applies it to two DSL classes BuilderA and BuilderB.

A
annotation class MyDslMarker

@DslMarker
class BuilderA

@DslMarker
class BuilderB
B
annotation class MyDslMarker

@MyDslMarker
annotation class BuilderA

@MyDslMarker
annotation class BuilderB
C
import kotlin.DslMarker

@DslMarker
annotation class MyDslMarker

@MyDslMarker
class BuilderA

@MyDslMarker
class BuilderB
D
import kotlin.DslMarker

@DslMarker
class MyDslMarker

@MyDslMarker
class BuilderA

@MyDslMarker
class BuilderB
Attempts:
2 left
💡 Hint

Remember that @DslMarker must annotate an annotation class, not a regular class.

🚀 Application
expert
2:30remaining
How many items are in the resulting list after running this Kotlin DSL code with @DslMarker?

Given the following Kotlin DSL code using @DslMarker, how many items does the items list contain after buildList() is called?

Kotlin
import kotlin.collections.mutableListOf

@DslMarker
annotation class ListDsl

@ListDsl
class ListBuilder {
    val items = mutableListOf<String>()
    fun item(value: String) {
        items.add(value)
    }
    fun nested(init: NestedBuilder.() -> Unit) {
        val nested = NestedBuilder()
        nested.init()
        items.addAll(nested.items)
    }
}

@ListDsl
class NestedBuilder {
    val items = mutableListOf<String>()
    fun item(value: String) {
        items.add(value)
    }
}

fun buildList(): List<String> {
    val builder = ListBuilder()
    builder.item("A")
    builder.nested {
        item("B")
        item("C")
    }
    return builder.items
}

fun main() {
    println(buildList())
}
A4
B2
C1
D3
Attempts:
2 left
💡 Hint

Count all items added to the main builder's list, including those added from the nested builder.