6 minutes read

In Kotlin, functions form the bedrock of your code. They define blocks of code that you can execute and reuse throughout your program. A function is a sequence of instructions put together to operate. In a way, it is a kind of subprogram.

Functions play a critical role because they organize code into manageable chunks. They enable code reuse, lighten redundancies, and enhance readability. When you wrap specific operations inside functions, you build more modular and maintainable codebases.

Basic syntax

A function has a name, so you can invoke it when you need it. Kotlin standard library has lots of functions, for example println(). If they are not enough, you can declare a new function and then invoke it the same way as a standard function.

To declare a new function, you need to indicate the fun keyword and a function name, a list of parameters in parentheses, and the type of the result value. So, it looks like this:

fun functionName(p1: Type1, p2: Type2, ...): ReturnType {
    // body
    return result
}

A function has the following components:

  • a name that follows the same rules and recommendations as a variable name;

  • a list of parameters in parentheses. Each parameter has a name and a type separated by a colon :. All the parameters are separated by commas ,;

  • the type of the return value (optional);

  • a body that contains statements and expressions;

  • the keyword return followed by the result (also optional).

The types of parameters and the result can be of any type including Int, Double, Boolean, String, and so on.

Defining a simple function

Let's declare a function that calculates the sum of integer numbers and then returns it.

fun sum(a: Int, b: Int): Int {
    val result = a + b
    return result
}

fun main() {
    val result1 = sum(2, 5)
    println(result1) // 7
    
    val result2 = sum(result1, 4)
    println(result2) // 11
}

When we invoke our function for the first time, we pass two values 2 and 5 to it. We assign them to a and b parameters respectively. The function returns the value of the result. The result type is the same as the type of the return value declared in the function (Int). When we invoke the function the second time, we pass the value of the result1, 7 and 4 as its arguments. The function returns 11.

The arguments of a function can be accessed only in the function.

Function parameters

As you may know, parameters represent the input data of a function. You can declare a function that takes one or more parameters of the same or different types. Also, you can declare a function that does not have parameters at all, but the parentheses are still required.

Here are some examples:

/**
 * The function returns its argument
 */
fun identity(a: Int): Int {
    return a
}

/**
 * The function returns the sum of two Ints
 */
fun sum(a: Int, b: Int): Int {
    return a + b
}

/**
 * The function just returns 3
 */
fun get3(): Int {
    return 3
}

fun add3(a: Int): Int {
    return identity(a) + get3()
}

fun main() {
    println(identity(1000)) // 1000
    println(sum(200, 300))  // 500    
    println(get3())         // 3
    println(add3(5))        // 8
}

As you can see, we can invoke a function from the main function, but it is also possible to invoke a function from another regular function, like in function add3().

Return type

A function can return a single value or nothing. If a function returns something, its body must have the return keyword followed by the result. Sometimes, you need a function that returns nothing. There are two ways to declare a function that returns nothing:

/**
 * The function prints the values of a and b
 */
fun printAB(a: Int, b: Int) {
    println(a)
    println(b)
}
  • specify the special Unit type as the return type:

/**
 * The function prints the sum of a and b
 */
fun printSum(a: Int, b: Int): Unit {
    println(a + b)
}

Function body

You can write any statements in a function body, for example, inside the main function. In addition to the parameters, you can declare new variables that are visible in the function only.

For example, this function extracts the last digit of a number and then returns it.

fun extractLastDigit(number: Int): Int {
    val lastDigit = number % 10
    return lastDigit
}

You can simplify this code by excluding the extra variable:

fun extractLastDigit(number: Int): Int {
    return number % 10
}

You can perform any operations in the function body. For example, this function uses a relational operation. It checks whether the number is positive or not:

fun isPositive(number: Int): Boolean {
    return number > 0
}

The function isPositive takes an integer number and returns a Boolean value because the result of the expression number > 0 is either true or false.

Take a look at one more example. The line after the return statement will not be executed (the so-called unreachable code):

/**
 * It returns "hello"
 */
fun getGreeting(): String {
    return "hello"   // Ends the function
    println("hello") // Will not be executed
}

Single-expression functions

If a function returns a single expression, you can write it without curly braces. It's an idiomatic way to create concise functions:

fun sum(a: Int, b: Int): Int = a + b

fun sayHello(): Unit = println("Hello")

fun isPositive(number: Int): Boolean = number > 0

Specifying the return type is optional, as it can be inferred automatically:

fun sum(a: Int, b: Int) = a + b // Int

fun sayHello() = println("Hello") // Unit

fun isPositive(number: Int) = number > 0 // Boolean

Conclusion

A Kotlin function is a special kind of expression that has a body, parameters, and some sort of return. Functions can make your code straightforward. It is always cool when you can decompose a program into small, clear, and comprehensible pieces. To make your code more readable, choose good names for your functions. Remember, a set of concise functions is always better than one big function that does just about everything. And don't forget about idioms.

1181 learners liked this piece of theory. 14 didn't like it. What about you?
Report a typo