Explain the difference between Kotlin's let, run, with, apply, and also

Whether you know the two axes of Kotlin scope functions: receiver (this vs it) and return value (context vs lambda result).
Group by this (apply, run, with) vs it (let, also), then by return type.
Using them randomly.
WHAT THIS TESTS: This question tests whether you understand Kotlin scope functions as a decision matrix rather than memorized syntax. Interviewers care that you can articulate the two dimensions that differentiate let, run, with, apply, and also: how the context object is referenced inside the lambda (this versus it) and what the overall expression returns (the context object versus the lambda result). A senior candidate should be able to pick the right function for a given pattern without hesitation and explain why nesting or chaining scope functions can hurt readability.
A GOOD ANSWER COVERS: A strong answer groups the five functions by receiver style and return value. The this-based functions are apply, run, and with; inside these lambdas you access the object as a receiver, omitting this when calling its members. The it-based functions are let and also; these use the lambda argument name it, which is better when you want to treat the object as a value rather than configuring its internals. Next, split by return value: apply and also return the context object itself, making them ideal for builder-style configuration or adding side effects. Let, run, and with return the lambda result, making them suitable for transformations or computations. A good answer also maps these to idiomatic use cases: apply for configuring an object before assignment, let for executing code on non-nullable objects or mapping a value, also for logging or validation side effects, run for running statements where an expression is required, and with for grouping multiple operations on an object when you do not need an extension call site. Finally, mention that with is not an extension function but takes the context object as an argument.
COMMON WRONG ANSWERS: A red flag is claiming the functions compile to different bytecode or have different performance characteristics; they are all inline functions with identical runtime cost. Another red flag is treating them as completely interchangeable; while they overlap, Kotlin style guides and team conventions favor specific functions for specific intents. Saying you always use let because it is the only one you remember suggests shallow familiarity. Overly complex nested scope functions are also a warning sign; the official documentation explicitly recommends avoiding nesting because it becomes hard to track whether this or it refers to which object.
LIKELY FOLLOW-UPS: An interviewer might ask when to prefer it over this in a scope function lambda. They might also ask you to refactor a nested scope function chain into readable code, or to explain how apply differs from a builder pattern. Another common follow-up is how scope functions interact with null safety, such as the safe call plus let idiom like obj?.let.
ONE CONCRETE EXAMPLE: For the apply use case, consider creating an Android TextView programmatically. You write val textView = TextView(context).apply { text = "Hello" textSize = 16f setTextColor(Color.BLACK) setPadding(16, 16, 16, 16) }. This returns the configured TextView instance, letting you assign it immediately without repeating the variable name for every property assignment.
Source: kotlinlang.org
Read the original → kotlinlang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.