Lambdas & Inline Functions Interview Questions
KOTLIN › Types & Classes
Walk me through the trade-off of marking a higher-order function inline: what do you gain, and what's the cost if you do it reflexively on every lambda-taking function?
What a strong answer covers: Marking a function inline avoids allocating a Function object for the lambda argument and avoids a virtual call through invoke(), which matters on genuinely hot paths, and it also unlocks non-local return and reified type parameters. The cost of doing it reflexively is that the compiler pastes the function's whole body plus the lambda body into every call site, so a large inline function called from many places bloats compiled bytecode and method count for a benefit that's usually immaterial outside of small, frequently-called utility functions.
You've got a large inline function whose body itself is fairly big, called from dozens of places. What's the actual downside on Android, and how would you decide whether to keep it inline or convert it to a regular function?
What a strong answer covers: Each call site gets a full copy of the function's bytecode pasted in, so a big inline function called from dozens of places multiplies its own size by the number of call sites, inflating APK size and method count, and it makes debugging slightly odd since stack traces don't show a distinct frame for the inlined function. The decision hinges on whether the function actually needs inlining for lambda performance, reified types, or non-local return; if it doesn't, inline should be dropped, and even if it does, a large body is a signal to extract the non-lambda-dependent logic into a regular helper called from within a small inline wrapper.
Non-local return from inlined lambdas is convenient but changes behavior when a lambda parameter is later marked noinline or crossinline, e.g. because it's now stored or run on another thread. Walk me through a scenario where this bites a team during a refactor, and how you'd catch it.
What a strong answer covers: If a lambda parameter starts as plain inline and its body uses a bare return to exit the enclosing function early, that only compiles because the parameter is directly inlined at the call site; the moment a refactor marks it noinline, to store it as a real object, or crossinline, because it now runs from another lambda or thread, the compiler flags every bare return in that lambda as illegal, since neither supports non-local return. The real danger is a developer 'fixing' the compile error by wrapping the return in a nested lambda without checking what the original early-exit was protecting; a strong answer describes auditing every call site's control flow, not just satisfying the compiler, whenever an inline function's parameter modifiers change.