Lambdas & Inline Functions Quiz

KOTLIN › Types & Classes

What is the primary performance benefit of marking a higher-order function inline?

Answer: It avoids allocating a function object and closure per lambda

Inlining pastes the lambda body at the call site, eliminating the function-object and closure allocation that a normal higher-order call would require.

Inside a lambda passed to the inline function forEach, a bare return will:

Answer: Return from the enclosing function that called forEach.

Because forEach is inline, the lambda body is inlined into the caller, so a bare return is a non-local return that exits the enclosing function.

You have inline fun run(crossinline body: () -> Unit). What does crossinline enforce?

Answer: The lambda may not perform a non-local return

crossinline keeps the lambda inlined but forbids non-local returns, which is required when the lambda is invoked from a different execution context such as an object or nested function.

When is noinline required on a lambda parameter of an inline function?

Answer: When you need to store, return, or pass it as a normal object

Inlined lambdas have no object representation, so to treat one as a value (store it, return it, pass to a non-inline function) you must mark it noinline.

Which statement about reified type parameters is correct?

Answer: They’re permitted only on inline functions, usable at runtime.

Reification depends on substituting the concrete type at each inlined call site, so reified is permitted only on inline functions; it then lets you use is T, as T, and T::class.

Regarding closures, how does Kotlin differ from Java?

Answer: Kotlin can capture and modify a var from the outer scope

Kotlin closures can read and mutate enclosing-scope variables, including a var, whereas Java requires captured locals to be final or effectively final.

Why can't a public inline function reference a private or internal declaration in its body?

Answer: The body is inlined into modules that can't access that symbol

The body is inlined into calling modules, so a non-public symbol would not be visible there; @PublishedApi internal is the escape hatch for needed internal declarations.

A bare return inside an anonymous function such as fun(x: Int) { ...; return } passed to forEach behaves how, compared to the same return inside a lambda?

Answer: It returns locally from the anonymous function, not the enclosing one

An anonymous function has its own return scope, so a bare return exits only that anonymous function (a local return); the same return in a lambda would be a non-local return from the enclosing function.

When a lambda captures and mutates a local var, how does the Kotlin compiler typically implement that capture on the JVM?

Answer: It wraps the var in a heap Ref.* holder so both share one cell

To let both the enclosing scope and the lambda see the same mutable value, the compiler wraps the captured var in a Ref.* holder object allocated on the heap, which is an allocation cost worth knowing about on hot paths.

Inside list.forEach { ... }, you want to stop processing the current element and move to the next without exiting the surrounding function. What is the idiomatic way?

Answer: Use return@forEach to skip just the current element

return@forEach is a labeled local return that ends only the current lambda invocation (the current element); break/continue are not allowed directly inside a lambda, and a bare return would exit the enclosing function.

Given inline fun <reified T> create(): T, why can't the body simply call T() to instantiate T?

Answer: Because reification enables type checks and reflection, not a no-arg constructor

Reification makes the concrete type usable for is T, as T, and T::class, but the compiler still cannot assume any particular constructor exists, so direct T() is disallowed; you would reflect via something like T::class.createInstance().

What does the Kotlin compiler do when you mark a function inline but it has no function-type (lambda) parameters?

Answer: It emits a warning that inlining offers little benefit

The main payoff of inline is removing lambda-object allocation, so with no lambda parameters the compiler warns that inlining brings negligible benefit; reified type parameters are the notable reason to inline such a function anyway.

On the JVM, a lambda passed to an ordinary (non-inline) function expecting a (Int) -> String is compiled to an instance of:

Answer: A class that implements kotlin.Function1<Int, String>

Non-inlined function values are realized as objects implementing the matching FunctionN interface (here Function1); that per-call object allocation is exactly what marking the calling function inline eliminates.

In numbers.filter { it > 0 }, which statement about the syntax is correct?

Answer: The last function-type argument can move outside, and it is implicit

Trailing-lambda syntax lets a final function-type argument be written outside the parentheses (which can be dropped when it is the only argument), and a single-parameter lambda exposes that argument implicitly as it.

Back to Lambdas & Inline Functions