Bird
Raised Fist0
Kotlinprogramming~20 mins

Configuration DSL pattern in Kotlin - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Kotlin DSL 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 configuration?
Consider this Kotlin DSL code that configures a server. What will be printed when running the main function?
Kotlin
class ServerConfig {
    var host: String = "localhost"
    var port: Int = 80

    fun printConfig() {
        println("Server running on $host:$port")
    }
}

fun server(block: ServerConfig.() -> Unit): ServerConfig {
    val config = ServerConfig()
    config.block()
    return config
}

fun main() {
    val config = server {
        host = "192.168.1.1"
        port = 8080
    }
    config.printConfig()
}
AServer running on localhost:80
BServer running on 192.168.1.1:80
CServer running on 192.168.1.1:8080
DServer running on localhost:8080
Attempts:
2 left
💡 Hint
Look at how the DSL block changes the properties inside ServerConfig.
🧠 Conceptual
intermediate
1:30remaining
Which Kotlin feature enables the Configuration DSL pattern?
Which Kotlin language feature is primarily used to create a Configuration DSL pattern like the example below? ```kotlin fun server(block: ServerConfig.() -> Unit): ServerConfig { val config = ServerConfig() config.block() return config } ```
AExtension functions with lambda receiver
BData classes with default parameters
CCompanion objects with factory methods
DSealed classes with inheritance
Attempts:
2 left
💡 Hint
Think about how the lambda can access ServerConfig's members directly inside the block.
🔧 Debug
advanced
2:30remaining
Why does this Kotlin DSL configuration fail to set the port?
Given this code, why does the port remain 80 instead of changing to 9090? ```kotlin class ServerConfig { var host: String = "localhost" var port: Int = 80 } fun server(block: ServerConfig.() -> Unit): ServerConfig { val config = ServerConfig() block() return config } fun main() { val config = server { host = "example.com" port = 9090 } println("${config.host}:${config.port}") } ```
AThe host property is set but port is shadowed by a local variable.
BThe port property is immutable and cannot be changed.
CThe server function returns a new ServerConfig ignoring the block changes.
DThe block() call is not invoked on the config instance, so it modifies nothing.
Attempts:
2 left
💡 Hint
Check how the block lambda is called inside the server function.
📝 Syntax
advanced
1:30remaining
Which option correctly defines a Kotlin DSL function with a lambda receiver?
Select the correct Kotlin function signature for a DSL function that takes a lambda with receiver of type Config and returns Config.
Afun configure(block: Config -> Unit): Config
Bfun configure(block: Config.() -> Unit): Config
Cfun configure(block: (Config) -> Unit): Config
Dfun configure(block: () -> Config): Config
Attempts:
2 left
💡 Hint
Look for the syntax that declares a lambda with receiver.
🚀 Application
expert
3:00remaining
How many items are in the resulting map after this Kotlin DSL runs?
Consider this Kotlin code using a DSL to build a map: ```kotlin class MapBuilder { private val map = mutableMapOf() fun entry(key: String, value: Int) { map[key] = value } fun build(): Map = map } fun map(block: MapBuilder.() -> Unit): Map { val builder = MapBuilder() builder.block() return builder.build() } fun main() { val result = map { entry("a", 1) entry("b", 2) entry("a", 3) } println(result.size) } ```
A2
B3
C1
D0
Attempts:
2 left
💡 Hint
Think about what happens when the same key is added twice in a map.

Practice

(1/5)
1. What is the main purpose of the Configuration DSL pattern in Kotlin?
easy
A. To write complex algorithms for data processing
B. To handle exceptions in a program
C. To create a simple and readable way to set up configuration using blocks
D. To manage database connections automatically

Solution

  1. Step 1: Understand the Configuration DSL pattern

    This pattern is designed to make configuration code simple and clear by using blocks with a configuration object as receiver.
  2. Step 2: Identify the main purpose

    The main goal is to write setup code that looks like a small language, making it easy to read and write configurations.
  3. Final Answer:

    To create a simple and readable way to set up configuration using blocks -> Option C
  4. Quick Check:

    Configuration DSL = simple setup blocks [OK]
Hint: Think: configuration setup made easy and readable [OK]
Common Mistakes:
  • Confusing DSL with general programming logic
  • Thinking it manages databases or exceptions
  • Assuming it is for algorithm implementation
2. Which Kotlin syntax correctly defines a configuration DSL block with a receiver?
easy
A. fun configure(block: () -> Unit) { block() }
B. fun configure(block: () -> Config) { val config = block() }
C. fun configure(block: Config) { block() }
D. fun configure(block: Config.() -> Unit) { val config = Config(); config.block() }

Solution

  1. Step 1: Identify the correct DSL block signature

    A configuration DSL block uses a receiver function type like Config.() -> Unit to allow calling config properties inside the block.
  2. Step 2: Check the function implementation

    fun configure(block: Config.() -> Unit) { val config = Config(); config.block() } creates a Config instance and calls the block with config as receiver, which is the correct pattern.
  3. Final Answer:

    fun configure(block: Config.() -> Unit) { val config = Config(); config.block() } -> Option D
  4. Quick Check:

    Receiver function type = fun configure(block: Config.() -> Unit) { val config = Config(); config.block() } [OK]
Hint: Look for Config.() -> Unit receiver syntax [OK]
Common Mistakes:
  • Using () -> Config instead of Config.() -> Unit
  • Passing Config instance as parameter instead of receiver
  • Omitting the receiver call inside the function
3. Given the code below, what is the output?
class Config { var name = ""; var enabled = false }

fun configure(block: Config.() -> Unit): Config {
    val config = Config()
    config.block()
    return config
}

fun main() {
    val c = configure {
        name = "Test"
        enabled = true
    }
    println("Name: ${c.name}, Enabled: ${c.enabled}")
}
medium
A. Name: Test, Enabled: true
B. Name: , Enabled: false
C. Name: Test, Enabled: false
D. Compilation error

Solution

  1. Step 1: Understand the configure function

    The configure function creates a Config object, applies the block to set properties, then returns it.
  2. Step 2: Analyze the block in main

    The block sets name to "Test" and enabled to true on the Config instance.
  3. Step 3: Check the printed output

    Printing c.name and c.enabled shows "Test" and true respectively.
  4. Final Answer:

    Name: Test, Enabled: true -> Option A
  5. Quick Check:

    Block sets properties correctly = Name: Test, Enabled: true [OK]
Hint: Block sets properties on Config instance returned [OK]
Common Mistakes:
  • Assuming default values remain unchanged
  • Thinking block does not modify config
  • Confusing syntax causing compilation error
4. What is wrong with this configuration DSL usage?
class Config { var port = 0 }

fun configure(block: Config.() -> Unit): Config {
    val config = Config()
    block()
    return config
}

fun main() {
    val c = configure {
        port = 8080
    }
    println(c.port)
}
medium
A. The block is called without receiver, so port is not set
B. Config class is missing a constructor
C. The configure function should return Unit, not Config
D. The println statement is incorrect

Solution

  1. Step 1: Check how block is called inside configure

    The block is called as block() without receiver, so it does not modify the config instance.
  2. Step 2: Understand the effect on port property

    Since the block does not apply to config, port remains 0, the default value.
  3. Final Answer:

    The block is called without receiver, so port is not set -> Option A
  4. Quick Check:

    Missing receiver call = The block is called without receiver, so port is not set [OK]
Hint: Call block with config.block() to apply receiver [OK]
Common Mistakes:
  • Calling block() instead of config.block()
  • Assuming default constructor is missing
  • Thinking return type causes error
5. How can you extend the Configuration DSL pattern to support nested configuration blocks for a server with database settings?
Choose the best approach.
hard
A. Use global variables for database settings inside the server config block
B. Define nested classes for ServerConfig and DatabaseConfig, then use nested receiver blocks
C. Pass database settings as strings to the server config block without nesting
D. Create separate functions for server and database config without nesting

Solution

  1. Step 1: Understand nested configuration needs

    To configure server and database settings clearly, nested blocks with receivers allow intuitive setup.
  2. Step 2: Use nested classes and receiver blocks

    Define ServerConfig with a DatabaseConfig property and provide a nested block to configure database inside server block.
  3. Step 3: Why other options are less suitable

    Global variables reduce clarity, passing strings loses structure, separate functions lose nesting benefits.
  4. Final Answer:

    Define nested classes for ServerConfig and DatabaseConfig, then use nested receiver blocks -> Option B
  5. Quick Check:

    Nested classes + blocks = Define nested classes for ServerConfig and DatabaseConfig, then use nested receiver blocks [OK]
Hint: Use nested classes and blocks for clear hierarchical config [OK]
Common Mistakes:
  • Using global variables instead of nested blocks
  • Passing unstructured strings for nested config
  • Avoiding nested blocks reduces readability
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard