Kotlin Tutorial · Advanced Kotlin · Lesson 28 of 31
Kotlin Context Parameters
Pass dependencies such as a logger or a transaction implicitly with context parameters, stable since Kotlin 2.4.
Implicit dependencies
Some values are needed by many functions (a logger, a database transaction, a user session). Passing them as
ordinary parameters through every call is noisy. Context parameters declare them once:
context(logger: Logger) fun .... A caller provides the context with with(value) { } or by being in a
function that has the same context itself.
Context parameters became stable in Kotlin 2.4 (they replace the older experimental context receivers).
interface Logger { fun log(message: String) }
class ConsoleLogger(private val prefix: String) : Logger {
override fun log(message: String) = println("[$prefix] $message")
}
context(logger: Logger)
fun reserveStock(sku: String) {
logger.log("reserved $sku")
}
context(logger: Logger)
fun placeOrder(id: Int, skus: List<String>) {
logger.log("placing order $id")
skus.forEach { reserveStock(it) } // the context is passed on implicitly
}
fun main() {
with(ConsoleLogger("orders")) {
placeOrder(42, listOf("mug", "teapot"))
}
}
Output
[orders] placing order 42 [orders] reserved mug [orders] reserved teapot
Run this on your computer — see “Get Started” for setup.
Test yourself
How does a caller supply a context parameter?
As the first normal argumentBy calling inside a scope that provides it, e.g. with(value) { }Through a global variableWith an annotation
Show answer
Answer: By calling inside a scope that provides it, e.g. with(value) { }