skip to content

Local & Nested Functions

A function declared inside another function closes over the enclosing locals, which is how you factor out repetition without leaking a helper into the class API. Local recursion and shared validation logic are the usual motivating cases.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

What is a local (nested) function in Kotlin, and what is the main reason to use one instead of a private top-level or member function?

level: juniorimportance: must knowfreq 55%

answer

  1. fun inside fun
  2. scoped to enclosing function only
  3. closes over outer locals/params
  4. good for one-off helpers + recursion
  5. captured var wrapped in Ref

basics

~20 s

A local function is a function declared inside another function. The main reason to use one is to reuse a small piece of logic that only matters to the surrounding function, while reading its local variables directly.

solid answer

~40 s

A local function is a `fun` declared inside the body of another function. It is only visible within its enclosing function's scope, so it keeps a helper private to where it's used. Crucially, it closes over the enclosing function's local variables and parameters, so you can read (and with `var`, mutate) them directly instead of threading them through parameters. That removes duplication without polluting the class with a `private` member that no other method needs. Typical uses: factoring out a repeated validation/transformation step inside one algorithm, or naming a recursive helper. Prefer it over a private member when the helper is meaningless outside the enclosing function and benefits from sharing its state.

code

kotlin · 6 lines
kotlin
fun greetAll(names: List<String>, greeting: String) {
    fun greet(name: String) = println("$greeting, $name!") // captures greeting
    names.forEach { greet(it) }
}

fun main() = greetAll(listOf("Ada", "Linus"), "Hello")

go deeper

for a junior

Knows the syntax (fun inside fun) and that it's only visible inside the enclosing function.

for a middle

Explains closure over locals/params and picks local function vs private member appropriately.

for a senior

Discusses return semantics, recursion, and the compiler's Ref wrapping for captured vars.

for a principal

Weighs readability/encapsulation trade-offs and when extracting to a private/top-level function is the better design at scale.

## What it is A **local function** (also called a **nested function**) is a function defined inside the body of another function using the normal `fun` keyword. Its **scope** — the region where its name is visible — is limited to the enclosing function. Code outside cannot call it. ```kotlin fun printArea(width: Int, height: Int) { // local function, only visible inside printArea fun label(prefix: String, value: Int) { // closes over nothing extra here, just a helper println("$prefix = $value") } label("width", width) label("height", height) label("area", width * height) } ``` ## Closure: the key benefit A local function forms a **closure** — it captures ("closes over") the variables and parameters of its enclosing scope and can use them directly: ```kotlin fun validateUser(name: String, age: Int) { fun fail(field: String): Nothing = throw IllegalArgumentException("$field invalid for user $name") if (name.isBlank()) fail("name") // reads enclosing `name` if (age < 0) fail("age") } ``` The local function `fail` reads `name` from the outer scope without it being passed in. This avoids repeating the user context in every call. ## When to use it vs alternatives - **vs a `private` member function:** use a local function when the helper is meaningless outside the one function and benefits from sharing its locals. A `private` member is right when several methods reuse it. - **vs a `private` top-level function:** same idea — top-level is for reuse across the file; local is for one-function-only logic. - **vs a lambda:** a local function can be recursive (it has a name) and reads more clearly for multi-line logic; a lambda is better when you need to pass behavior as a value. ## Mechanics to know - Declared with `fun`, can have parameters, a return type, generics, and even nested local functions. - Can capture both `val` (read) and `var` (read and mutate) from the enclosing scope. - A bare `return` inside a local function returns from the **local function**, not the enclosing one (unlike an inline lambda). - Under the hood the compiler typically generates a synthetic class/method; captured `var`s are wrapped in a `Ref` holder so changes are visible to both scopes. ## Common idioms - **Factor recursion:** name a recursive helper inside a public function so the recursion isn't exposed. - **Share state:** accumulate into an enclosing `var`/collection without passing it around.

  • Can a local function be called before it is declared in the enclosing function?
    No. Like local variables, a local function must be declared before the line that calls it; it isn't hoisted.
  • Does a bare `return` inside a local function return from the outer function?
    No — it returns from the local function itself. Only inline lambdas allow a non-local `return` to the enclosing function.

Like a sticky note you write for yourself inside one task — useful right there, but you don't pin it to the whole office wall.

saying these in an interview costs you the question

  • Claiming a local function is visible/callable from outside its enclosing function
  • Saying local functions cannot access the outer function's variables
  • Confusing a local function with a lambda and thinking `return` exits the outer function
  • Asserting they hurt performance significantly in normal code
  • Saying you must pass all outer state as parameters

context

open as a page

Show how to factor a recursive algorithm into a local function. Why is a local function often preferred over exposing the recursive helper as a separate public/member function?

level: middleimportance: should knowfreq 45%

basics

~20 s

Put the recursive part in a function declared inside the public one. It keeps the recursion private and lets it reuse the outer parameters, so the public function's signature stays clean and the helper can't be misused from outside.

open as a page

Compare `return` behavior in a local function versus in a (non-inline and inline) lambda. What surprises candidates here?

level: middleimportance: should knowfreq 35%

basics

~20 s

In a local function, a plain return just exits that local function. In a lambda, a plain return is only allowed when the lambda is inlined, and then it exits the whole outer function. That difference trips people up.

open as a page

When would you reach for a local function instead of a lambda (or vice versa)? Give concrete decision criteria.

level: middleimportance: should knowfreq 30%

basics

~20 s

Use a local function for multi-step named helper logic, especially if it must recurse or read clearly. Use a lambda when you need to pass behavior as a value into another function, like into map or forEach.

open as a page

A local function captures and mutates a `var` from its enclosing function. Explain what the compiler does under the hood and what subtle behavior this can cause.

level: seniorimportance: should knowfreq 30%

basics

~20 s

Kotlin lets a local function change an outer var. Behind the scenes the variable is boxed in a small holder object so both the outer code and the inner function see the same value. Changes made inside are visible outside.

open as a page