Cookie Preferences

We use cookies to enhance your experience. Choose your preference for cookie usage.

Essential cookies are required for basic functionality. Additional cookies help us improve our service and provide analytics.

View third-party services
  • Google Analytics: Website traffic analysis and conversion tracking
  • RudderStack: Analysis of user interactions with the website
  • Microsoft Clarity: User behavior analysis & session recordings
  • Facebook Pixel: Marketing analysis of user activity
KotlinFunction

Declaring functions

Program decomposition

As you may know, a function is a sequence of instructions grouped together to perform an operation – it is a kind of subprogram. A function has a name to invoke it when you need to. Kotlin's standard library has a lot of functions, such as println, but when those are not enough, you can declare a new function and then invoke it in the same way as any standard function.

The main reason to declare new functions is to divide a program into small reusable subroutines. The term for this in computer science is decomposition. Subroutines can be called as many times as you like, instead of repeatedly inserting the same block of code. A decomposed program has a modular structure and it is much easier to modify and maintain than a program consisting of a single main function with thousands of lines of code. This idea comes from procedural programming.

Basic syntax of a function

To declare a new function you should write the keyword fun followed by a name, a list of parameters in parentheses, and the type of result value. So, it should look 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 the name of a variable;
  • a list of parameters in parentheses to represent input data, each parameter has a name and a type separated by a colon :, all parameters are separated by commas ,;
  • the type of return value (optional);
  • a body containing statements and expressions to perform the operation.
  • the keyword return followed by the result (not always required).
The types of parameters and a result can have any type including Int, Double, Boolean, String, and so on.

Defining a simple function

As an example, let's declare a function that calculates the sum of integer numbers and then invoke it from main.

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

fun main(args: Array<String>) {
    val result1 = sum(2, 5)
    println(result1) // 7
    
    val result2 = sum(result1, 4)
    println(result2) // 11
}

When we invoke the function sum for the first time, we pass the two values 2 and 5 to it. Inside the function, these values are assigned to the arguments a and b respectively. The function returns the value of the result variable to the place where we invoked it. The type of the result 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 result1 (7) and 4 as its arguments. The function returns 11.

Note that the arguments of a function are available only from the function.

Function' parameters

As you may know, parameters represent the input data of a function. It is possible to 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; just remember that parentheses are still required.

Here are several 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 main(args: Array<String>) {
    println(identity(1000)) // 1000
    println(sum(200, 300)) // 500    
    println(get3()) // 3
}

As you see above, we can invoke a function from the main function, but it is also possible to invoke a function from another regular function.

Return type

A function can return a single value or nothing. If a function returns something, its body must have the keyword return followed by the result. We have already seen some examples above.

Sometimes, you need a function that returns nothing. We will learn the reasons to use such functions later, but one of them is to print something to the standard output.

There are two ways to declare a function that returns nothing:

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

The first way (without Unit) is preferred in Kotlin programming.

Function' body

In the body of a function, you can write any statements, just like inside the main function. In addition to parameters, you can declare new variables which are visible only within the function.

For example, the following 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 body of a function. As another example, the following function demonstrates using a relational operation. It checks if the given number is positive (i.e., is greater than 0):

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.

Note: The line after the return statement will not be executed (unreachable code).

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

It is pointless to write unreachable lines in your functions, and clutters up your code, so you should avoid doing so..

Single-expression functions

If a function returns a single expression, the body can be written without curly braces:

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, 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

Sometimes we will specify the types and sometimes - no. If your function has only a single expression, try to use this form.

Conclusion

Define a new function if you plan to reuse a part of your code. This code snippet should be well-separated with a clear purpose. Functions allow you to decompose a program into small, clearly comprehensible subroutines and manage them conveniently. To make your code more readable, choose meaningful names for your functions.

Remember, a set of concise functions is better than one big function that does everything.
How did you like the theory?
Report a typo