Phase 2 · Functions & FunctionalModule 12~34 min read

Function Types, Inline & References

Store and pass functions, and understand inline functions and reified types.

What you'll learn

This module ties functional Kotlin together. You'll formalise function types, understand the inline keyword that makes higher-order functions fast, meet reified type parameters, and use function references cleanly.

By the end you'll be able to:

  • Read and use function types
  • Understand what inline does and why it matters
  • Use reified type parameters
  • Use function, property, and constructor references

Function types

A function type describes a function's shape: its parameter types and return type, joined by an arrow. (Int, Int) -> Int means "takes two Ints, returns an Int." You can store functions in variables of these types, and pass or return them:

Anatomy of a function type
(Int, Int) -> Int

Parameter types

The types the function accepts, in parentheses.

Return type

After the arrow — what it produces.

FunctionTypes.kt
// a variable holding a function, typed as (Int, Int) -> Int
val operation: (Int, Int) -> Int = { a, b -> a + b }
println(operation(3, 4))   // 7

// a function that RETURNS a function
fun operator(symbol: String): (Int, Int) -> Int = when (symbol) {
    "*" -> { a, b -> a * b }
    else -> { a, b -> a + b }
}

val multiply = operator("*")
println(multiply(3, 4))    // 12

inline functions

Passing lambdas around normally creates small objects at runtime, which has a tiny cost. The inline keyword tells the compiler to copy the lambda's code directly into the call site instead — eliminating that overhead. This is why Kotlin's collection operations (all those map/filter calls) are as fast as hand-written loops:

Inline.kt
// 'inline' copies the lambda's code into the call site — no lambda
// object is created. This makes higher-order functions as fast as a
// hand-written loop, which is why the stdlib functions are inline.
inline fun runTwice(action: () -> Unit) {
    action()
    action()
}

runTwice {
    println("Running!")
}

Note

Use inline for small higher-order functions where the lambda overhead matters. For everyday code you rarely write it yourself — but understanding it explains why Kotlin's functional style carries no performance penalty. (noinline and crossinline fine-tune the behaviour.)

reified type parameters

Normally, generic type information is erased at runtime (Module 22), so you can't write value is T. But inside an inline function, a reified type parameter keeps the type — letting you check and use it at runtime. It's a small superpower:

Reified.kt
// 'reified' lets you use the type T at runtime — only in inline functions
inline fun <reified T> firstOfType(items: List<Any>): T? =
    items.firstOrNull { it is T } as? T

val mixed = listOf(1, "hello", 2.0, "world")
println(firstOfType<String>(mixed))   // hello
println(firstOfType<Int>(mixed))      // 1

Function, property & constructor references

When a lambda would just call one existing function, a reference with :: says the same thing more concisely. There are three flavours: function (::triple), property (String::length), and constructor (::Person):

References.kt
fun triple(n: Int) = n * 3

val nums = listOf(1, 2, 3)
println(nums.map(::triple))        // [3, 6, 9]  — function reference
println(nums.map { triple(it) })   // [3, 6, 9]  — equivalent lambda

Recap & quick check

Key takeaways

  • A function type like (Int, Int) -> Int describes parameter types and a return type.
  • inline copies a lambda's code into the call site, removing overhead — why Kotlin's functional style is fast.
  • reified type parameters (only in inline functions) keep the type at runtime, enabling value is T.
  • References with :: point to a function (::name), property (Type::prop), or constructor (::Type).
  • You rarely write inline yourself, but it's why higher-order functions carry no performance penalty.

Quick check

1. What does the function type (String) -> Int mean?

2. What does the 'inline' keyword do?

3. Where can you use a 'reified' type parameter?

4. What does ::triple represent?

5. Why are Kotlin's map/filter operations fast despite using lambdas?

Excellent — you've completed Phase 2! You command lambdas, collection pipelines, scope functions, and extensions — the tools that make Kotlin so expressive. Next comes Phase 3 — Object-Oriented Kotlin.