Kotlin Functions

A function is a reusable portion of code that will perform a specific task. They encapsulate one or more tasks and can be reused throughout the code avoiding repetition. Kotlin (and other languages) provide a myriad of functions that help us write code like the println() function, for example, that will print things to the console and add a line break after it. But we can also create our own functions so we can reuse the code we created in other parts of the program.

So, for example, let’s say you want to sum up 2 numbers and instead of writing the code to perform the sum every time you need it, you can create a function that will perform the sum and when you need to use it you simply call the function and pass the parameters.

How to create a function

A function is basically composed of the header and the body. To create a function you need the function declaration key which in Kotlin is fun then you need a name. Function naming conventions are the same as variables, so you can use the camelCase practice here too.

You also need to specify the function visibility. By default, all functions in Kotlin are public, which means they can be accessed and used from any function in the program including functions that are defined on other files. Private functions, on the other hand, can only be accessed within a specific scope. Private functions are very useful when you need to keep specific information from being accessed from other parts of the program, especially the interface (the user-facing part). It’s just a form of controlling where the information goes and what can be done with it.

Next comes the function parameters. They specify the name and the type of information that will be required by the function so it can do its magic. So, in the case above we have two variables (a and b) of type Int that will be used in the function. When you call this function somewhere else you will need to provide the arguments (the actual values to the parameters that are declared in the function).

In other words, when you create a function you say “Hey, this function named addNumbers will need two parameters that will be called a and b and they are both Ints. If you need to use this function to add two numbers you can provide the arguments for the function to work and these arguments are the two numbers you want to add.”

This way when you call the function to use it, you provide the numbers you want to be added (the actual values for the function parameters or the arguments). One number will be stored in the variable named a and one in the variable named b. The function will then add them up and store the result in the variable we created called, well… result.

Functions can require a number of parameters depending on what they will do or they might not require any parameters. One function can have parameters of different types. The same function can use two Ints and a String, for example.

If a function generates an output, the next element will be the function return type. It will define what type of data that specific function will return when it is called. The combination of the function parameters and return type is also called the function signature. If your function does not return any data you can omit the return type from the function signature.

đź“Ś  Worth Noting, as mentioned above, some functions might not require any parameters at all. See the example below:

You can create a function that will print the results of addNumbers. So printResult does not take any parameters. You use the println() function to prin the addNumbers function and pass the arguments there. Then you can call printResult without providing any arguments. I’m not saying this is super useful in this specific example, but it’s just to illustrate that it can be done and functions without parameters exist.

After the function header, comes the function body which is where you will actually say what that specific function will do. In this case, the body of the function will contain the instructions to add the two provided numbers and return the result.

In this case, the function is super simple and has only one line of code but it is what defines what the function will do which is add the value stored in the variables a and b.

Default Arguments

Sometimes one of the parameters of a function would have a probable value and in this case, you can set this value as a default argument directly in the function to avoid repeating it when you call that function later, especially if you need to call the function several times.

So let’s consider the following functions:

private fun destroyRing(
    playerLevel: Int,
    playerRace: String,
    hasRing: Boolean
): String {
    return when (playerLevel) {
       in 1..4 -> "You don't have the strength to destroy the ring"
       in 5..9 -> {
            if (playerRace == "Hobbit" && hasRing) {
                "I see your potential little one. You look like you could save us from Sauron"
            } else if (playerRace == "Hobbit" && !hasRing){
                "You don't a ring to destroy. Go find the ring first"
            }
            else {
                "You don't have the means to destroy the ring"
            }
        }
        10 -> if (playerRace == "Hobbit" && hasRing) {
            "You are ready little one. Go and throw the ring into the fires of Mount Doom"
        } else if (playerRace == "Hobbit" && !hasRing){
            "You don't a ring to destroy. Go find the ring first"
        }else {
            "You don't have the means to destroy the ring. Only a hobbit can do it"
        }
        else -> "I have no idea what you are talking about."
    }
}

Then you call a println function to print the result based on the arguments you passed:

If throughout the adventure you need to check multiple times if a specific character can destroy the ring you would need to call the function and provide all 3 arguments all the time. If you don’t the IDE will complain saying that function is expecting a third argument that was not provided:

Now, let’s say the probability of a character getting to the end of the quest without a ring is pretty low because they are awesome and have an amazing group of heroes in their party that would never allow them to lose the ring. In this case, you can set the default value of hasRing to true to avoid having to pass this argument every time you call the function unless the value is actually different.

So the function would look like this:

And when you call the function you can omit the hasRing argument unless it’s actually false.

Kotlin Syntax

As I mentioned here, one of the big things about Kotlin is that you can write the same code as you would do in Java, for example, in fewer lines. In other words, it’s more concise and, for some people, it’s clearer. To me, as someone who started programming with Kotlin, I found it very confusing in the beginning. I find Java way easier to read and understand. But, this is Kotlin, so here we go.

In programming, a statement to be evaluated (a piece of code that will be read/analyzed/ ran by the program to have its value determined) like when you call a function or declare a variable – is called an expression. So, a function that has only one expression is called a Single-Expression Function which is the case for destroyRing (I know there is a lot of code there but it is only one expression which is the When statement). When that happens, Kotlin allows you to omit the return type, the curly braces AND the return keyword. So this is how the destroyRing function would look like:

private fun destroyRing(
    playerLevel: Int,
    playerRace: String,
    hasRing: Boolean
) = when (playerLevel) {
       in 1..4 -> "You don't have the strength to destroy the ring"
       in 5..9 -> {
            if (playerRace == "Hobbit" && hasRing) {
                "I see your potential little one. You look like you could save us from Sauron"
            } else if (playerRace == "Hobbit" && !hasRing){
                "You don't a ring to destroy. Go find the ring first"
            }
            else {
                "You don't have the means to destroy the ring"
            }
        }
        10 -> if (playerRace == "Hobbit" && hasRing) {
            "You are ready little one. Go and throw the ring into the fires of Mount Doom"
        } else if (playerRace == "Hobbit" && !hasRing){
            "You don't a ring to destroy. Go find the ring first"
        }else {
            "You don't have the means to destroy the ring. Only a hobbit can do it"
        }
        else -> "I have no idea what you are talking about."
    }

Instead of using the function body to specify the work, the function will perform, with single-expression function syntax you use the assignment operator (=), followed by the expression. You can also remove the function return type because just like Kotlin can infer variable types, it can infer the return type of a function if it has only one single expression.

That said, this function above had a pretty wordy When expression, so leaving the return type to improve the readability. So the function header would look like this:

private fun destroyRing(
    playerLevel: Int,
    playerRace: String,
    hasRing: Boolean
): String = when (playerLevel) { ...

Kotlin Programming – The Big Nerd Ranch Guide

Named Function Arguments

Let’s say you will create a function to help players create their characters in a game and the function will then print their character information.

private fun createChar(
    charName: String,
    charRace: String,
    charClass: String,
    charWeapon: String,
    charLevel: Int,
): String {
    return " Character name: $charName \n Character Race: $charRace \n Character Class: $charClass \n" +
            " Character Weapon of choice: $charWeapon \n Character Level: $charLevel"

}

Note that this function takes 5 different parameters. So, when you call it to create a character, you can do the following:

println(createChar("Legolas", "Elf", "wood elf fighter", "Bow", 20))

But, when you have a lot of parameters and your code is not just a few lines long, it can get a bit tricky to pass all the arguments in the correct order. So, to make sure you are passing the right arguments you can use what is called Named Function Arguments which is exactly what the name suggests: You pass the arguments when you call a function naming each parameter and this way you don’t need to worry about passing them in the right order. So it could read like this:

println(createChar(
    charRace = "Elf",
    charClass = "Wood Elf Fighter",
    charName = "Legolas",
    charWeapon = "Bow",
    charLevel = 20
))

When you do not use named function arguments, you must pass arguments in the order they are defined in the function header. Using it can improve your code readability and avoid mistakes.

Unit Functions

Just like not all functions have a parameter (or parameters), not all functions return something. Some functions just modify a variable or simply call other functions and these functions provide an output. The main function, for example, it uses the println( ) function to return something.

fun main() {

    print(destroyRing(10, "Hobbit"))
}

private fun destroyRing ...

In Kotlin, these functions that don’t return anything are called Unit Functions, meaning their return type is Unit. When you don’t specify the return type of a function Unit is automatically used.

This might sound weird but it solves an issue other languages face. In Java, for example, when a function does not return anything you can use the keyword void to specify that function won’t return anything:

public static void functionName() {
       println(xyz);
}

The issue with this is that void is not a type. It is not assigning a return type void to that function. It is simply saying to the compiler “this function does not return anything. Skip it”, which would be fine if it wasn’t for an important feature of modern languages called Generics (another type of function). To be able to work with Generics a function must have a type and Kotlin solves this issue by assigning the type Unit to “void” functions instead of simply saying the type information is not relevant and can be ignored.

Published by Rosie M

Android bug creator and full-time nerd. Joined Automattic in 2017. Passionate about music, books, games, photography and Doctor Who. Open-source enthusiast, remote-work advocate and Globetrotter.

2 thoughts on “Kotlin Functions

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: