Kotlin Functions
Declare reusable code blocks with parameters, return types, defaults, recursion, and inline optimization
Table of Contents
1Functions
A function is a reusable block of code that performs a specific task. In Kotlin, functions are declared with the fun keyword and can exist at the top level (outside any class) — unlike Java where methods must belong to a class.
Basic function syntax
Top-level vs member functions
| Type | Location | Example |
|---|---|---|
| Top-level | Directly in a .kt file | fun main(), utility helpers |
| Member | Inside a class or object | class User { fun display() } |
| Extension | Outside class, extends type | fun String.capitalizeWords() |
When a function body is a single expression, use = expression instead of { return ... }. The return type can be inferred automatically.
2Parameters
Parameters are variables listed in the function signature. Each parameter has a name and a type. Kotlin supports multiple parameters, vararg, and no parameters at all.
Multiple parameters
vararg — variable number of arguments
Parameter rules
| Rule | Description |
|---|---|
| Type required | Every parameter must have an explicit type |
| One vararg max | Only one vararg per function; usually last |
| Immutability | Parameters are val — cannot be reassigned |
| Spread operator | *array unpacks array into vararg arguments |
fun sayHello() { println("Hi!") }
3Return Types
Functions that return a value must declare a return type after the parameter list. Functions that return nothing use Unit (similar to Java's void).
Single-expression return (type inferred)
Return type reference
| Return type | Meaning | Example |
|---|---|---|
Int, String, etc. | Returns a value | fun getAge(): Int |
Unit | No meaningful return (optional to write) | fun printLine(): Unit |
Nothing | Never returns (throws or infinite loop) | fun fail(): Nothing |
| Nullable | May return null | fun find(): String? |
Use return anywhere in the function body to exit early — useful in validation and guard clauses.
4Default Arguments
Kotlin lets you assign default values to parameters. Callers can omit those arguments and the default is used — reducing overloaded method duplication common in Java.
Kotlin vs Java overloading
| Approach | Java | Kotlin |
|---|---|---|
| Multiple signatures | Overload methods with different params | Single function with defaults |
| Example | connect(), connect(host), connect(host, port) | connect(host = "localhost", port = 8080) |
5Named Arguments
Named arguments let you pass values by parameter name instead of position. This improves readability when a function has many parameters of the same type or when skipping defaults in the middle.
When named arguments help
Readability
send(to = user, subject = "Hi", body = msg) is clearer than positional args.
Any order
Pass arguments in any order when all are named.
Skip defaults
Override only the params you need without filling every slot.
Compose / UI
Jetpack Compose APIs rely heavily on named parameters.
Once you use a named argument, all following arguments must also be named. Positional arguments must come before named ones.
6Recursion
Recursion occurs when a function calls itself to solve a problem by breaking it into smaller subproblems. Every recursive function needs a base case to stop the chain of calls.
Fibonacci sequence
Tail recursion
Kotlin optimizes tail-recursive functions (recursive call is the last operation) with the tailrec modifier — converting recursion to a loop at compile time to avoid stack overflow.
| Concept | Description |
|---|---|
| Base case | Condition that stops recursion (e.g. n <= 1) |
| Recursive case | Function calls itself with a smaller input |
| Stack overflow | Too many calls without base case — use tailrec or loops |
| tailrec | Must call itself as the final operation only |
for or while — see Control Statements.
7Inline Functions
An inline function is marked with the inline keyword. The compiler copies the function body at each call site instead of creating a lambda object — reducing overhead when passing functions as parameters (higher-order functions).
Why use inline?
| Benefit | Explanation |
|---|---|
| Performance | Avoids object allocation for lambdas on each call |
| Reified generics | inline fun <T> with reified T — access type at runtime |
| Non-local returns | Lambda can return from enclosing function when inlined |
Reified type parameters
noinline and crossinline
| Modifier | Purpose |
|---|---|
noinline | Exclude a lambda parameter from inlining (pass to another function) |
crossinline | Lambda must not use non-local return; can be called from nested context |
Avoid inline on large functions — code duplication increases bytecode size. Use inline mainly for small higher-order functions. Learn more in Lambda & Higher-Order Functions.
8Summary Cheatsheet
| Topic | Key Takeaway |
|---|---|
| Functions | fun name(params): ReturnType { body }; top-level allowed |
| Parameters | Typed, immutable; vararg for variable args; spread with * |
| Return Types | Explicit or inferred; Unit = void; single-expression = |
| Default Arguments | param: Type = value — reduces Java-style overloads |
| Named Arguments | fn(name = "x", age = 10) — any order, skip defaults |
| Recursion | Base case required; tailrec for optimized tail calls |
| Inline Functions | inline fun — no lambda object; enables reified |
| Next lesson | Null Safety — nullable types and safe calls |
Kotlin Functions MCQ Practice
10 Basic MCQs 10 Advanced MCQs10 Basic Kotlin Functions MCQs
Which keyword is used to declare a function in Kotlin?
fun keyword — e.g. fun greet(name: String): String.Unlike Java, Kotlin allows functions to be declared where?
fun main() can live directly in a .kt file without a enclosing class.What is Kotlin's equivalent of Java's void return type?
Unit means no meaningful return value; it can be omitted from the signature.For a single-expression function, which syntax is idiomatic?
= expression for single-expression bodies; the return type is often inferred.Which feature lets callers omit arguments and use predefined values?
fun greet(name: String, greeting: String = "Hello") reduces Java-style overload duplication.When all arguments at a call site are named, you can pass them in?
createProfile(age = 30, name = "Alex").Which modifier accepts a variable number of arguments of the same type?
fun sum(vararg numbers: Int) packs multiple values; only one vararg per function is typical.Which modifier tells the compiler to optimize tail-recursive calls into a loop?
tailrec requires the recursive call to be the last operation — avoiding stack overflow on deep recursion.inline functions are especially useful when?
filter and map.reified type parameters require the function to be?
inline fun <reified T> preserves generic type info at runtime for checks like value is T.10 Advanced Kotlin Functions MCQs
Extension functions add behavior without?
fun String.capitalizeWords() extends a type statically — no subclass or inheritance required.In an inline function with multiple lambda parameters, noinline means?
noinline keeps a lambda as a real object — useful when passing it to another non-inline function.crossinline on a lambda parameter means?
crossinline restricts non-local returns when the lambda is invoked from nested inline contexts.To expose Java-friendly overloads from Kotlin default parameters, annotate with?
@JvmOverloads generates overloaded methods for Java callers who cannot use default arguments.Every recursive function must include?
if (n <= 1) return 1), recursion never terminates and causes stack overflow.In fun double(x: Int) = x * 2, the return type is?
Int.Kotlin function parameters are treated as?
val locals; reassigning a parameter is a compile error.To pass an array to a vararg parameter, use?
sum(*scores) unpacks an IntArray into individual vararg arguments.Functions declared inside another function are?
Inlining very large functions can?
Kotlin Functions Interview Q&A
15 topic-focused questions for interviews and revision.
fun name(param: Type): ReturnType { body } — e.g. fun greet(name: String): String { return "Hello, $name" }. Parameters require explicit types.fun main()). Member functions belong to a class or object. Both use the fun keyword.Unit and when you omit it.easyUnit is like Java void — the function returns no meaningful value. You can omit : Unit from the signature when there is no return value.fun connect(host: String = "localhost", port: Int = 8080). Callers omit arguments to use defaults, replacing multiple Java overloads with one function.vararg work and what is the spread operator?mediumvararg packs multiple values into an array inside the function. Use *array at the call site to expand an existing array into separate arguments.fun max(a: Int, b: Int) = if (a > b) a else b uses = instead of a block with return. Return type is inferred from the expression.n <= 1. Without a base case, stack overflow occurs.tailrec and when should you use it?hardtailrec marks tail-recursive functions where the recursive call is the last operation. The compiler rewrites it as a loop, avoiding deep call stacks for large inputs.inline functions?mediuminline copies the function (and lambda) body at each call site, avoiding lambda object allocation overhead in higher-order functions and enabling non-local returns from lambdas.reified type parameters?hardinline fun <reified T>, generic type T is available at runtime for checks like value is T. Normally type erasure removes generic info on the JVM.noinline and crossinline?hardnoinline prevents inlining a specific lambda (so it can be stored or passed elsewhere). crossinline allows inlining but forbids non-local return from that lambda.@JvmOverloads do?mediuminline on large functions — bytecode grows because the body is duplicated at every call site. Reserve inlining for small higher-order utilities.