๐ŸŽ“ A1Learner
๐Ÿ”
0 of 28 lessons completed

Kotlin Context Parameters

A context parameter lets a function declare a value it needs from its surroundings. The caller supplies that value by holding it in scope at the call.

One context value for a greeting

The greet function declares that it needs a User. The with block holds a user in scope, so the call inside the block can run.

class User(val name: String)

context(user: User)
fun greet(): String {
    return "Hello, " + user.name
}

fun main() {
    val ana = User("Ana")
    with(ana) {
        println(greet())
    }
}

A different value in each scope

The same greet function runs in two with blocks. Each block holds a different user, so each call greets a different name.

class User(val name: String)

context(user: User)
fun greet(): String {
    return "Hello, " + user.name
}

fun main() {
    val ana = User("Ana")
    val ben = User("Ben")
    with(ana) {
        println(greet())
    }
    with(ben) {
        println(greet())
    }
}

Two context values at once

This function needs a User and a GreeterConfig. Nested with blocks hold both values in scope, and the body reads both of them.

class User(val name: String)

class GreeterConfig(val greeting: String)

context(user: User, config: GreeterConfig)
fun greetWithConfig(): String {
    return config.greeting + ", " + user.name
}

fun main() {
    val ana = User("Ana")
    val config = GreeterConfig("Welcome")
    with(ana) {
        with(config) {
            println(greetWithConfig())
        }
    }
}

A badge from the context value

The badge function also declares a User as its context. Its body builds a short label from the name of the user in scope.

class User(val name: String)

context(user: User)
fun badge(): String {
    return "Badge for " + user.name
}

fun main() {
    val cid = User("Cid")
    with(cid) {
        println(badge())
    }
}

Example

class User(val name: String)

class GreeterConfig(val greeting: String)

context(user: User)
fun greet(): String {
    return "Hello, " + user.name
}

context(user: User, config: GreeterConfig)
fun greetWithConfig(): String {
    return config.greeting + ", " + user.name
}

fun main() {
    val ana = User("Ana")
    val config = GreeterConfig("Welcome")
    with(ana) {
        println(greet())
        with(config) {
            println(greetWithConfig())
        }
    }
}

Key points

  • A function declares the values it needs as context parameters.
  • The body reads a context value by its parameter name.
  • The caller must have a matching value in scope when the call runs.
  • A with block can supply the value for the calls inside the block.
  • A function can declare two context parameters when it needs two values.
  • Each call can receive a different value from a different scope.

In this example, the first call runs with only a user in scope and prints a plain greeting. The nested block adds a config value, so the second function can read both values and print its configured greeting.

Note

The function states what it needs, and the call site provides it.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท Kotlin Playground

Exercise

What must the caller of a function with a context parameter do?