Very Basics Of Kotlin Functions

JAVING
6 min readMar 9, 2021

--

As you start diving into Kotlin you will notice how incredibly versatile this language is. One of the many features that make it so versatile is that it is a multi-paradigm language.

Standalone functions
With Kotlin, we are not forced to code in an OO(Object Oriented) style if we don’t want. Unlike Java where classes are the smallest construct that can be re-used, Kotlin gives us both functions and classes as re-usable constructs.

Either if we are coding in a Kotlin file(.kt) or in a Kotlin script file(.kts), we can create standalone functions, without needing the class boilerplate.

A Kotlin script with a standalone function

Single-Expression functions
Above in the previous code example, we can see what is known as a Single-Expression function or also sometimes referred to as short function. In this functions the declaration is separated from the body by an ‘=’ operator instead of by the classic curly braces ‘{}’.

In short functions(only) the return type will be inferred at compilation time if is not provided. Also in short functions, the return keyword is not allowed. In the following example we are going to see an example that will fail to compile due to this automatic type inference.

Type inference compilation error will occur

A good practice is to specify they return type of the function if the function is an external API or if the function is more complex. To specify the return type yo a function all you need to do is add a ‘:’ after the parameters closing bracket.

Providing the return type to a function

Unit return type
Even if Kotlin is a multi-paradigm language it does favour, or at least encourages to take advantage of the usage of expressions over the usage of statements. This means that in Kotlin every function we create must return something so that expressions can be connected one after another in a more functional like style.

As opposed to Java where we have a void methods, in Kotlin we have the Unit type to represent that we are not returning anything.

If a Kotlin function is not returning anything, the Unit type will be inferred.

Compilation problem due to code inferring Unit by default.

The above code will throw a compilation error indicating a type mismatch because the salute() function does not have a return type specified and therefore the default is Unit. In the following code is the fixed version which shows that we can either remove the String type from the variable to take advantage of inference or just add the type Unit as the type of the variable

Line 2 shows type inference and line 3 explicitly shows the Unit type being declared

Using parameters in single-expression functions
In the previous part I said that Kotlin has type inference when it comes to return types. In parameters, that is not the case. Kotlin does not have type inference in function parameters. In Kotlin we must provide types to our parameters. If the function has multiple parameters, then they need to be separated with a comma.

Parameters must declare a type and must be separated with a comma

Functions with body
All the previous examples were small functions with a single expression. When functions are a bit more complex, we need to use blocks. A block starts with an open curly brace ‘{’ and ends with a close one ‘}’. To use a block in a function in Kotlin, we need to place it after a the parameters.

An example of a function with body

In functions with body, the return type is always mandatory and if the return type of the function is not specified then the function will by default return Unit. In the above example we could remove the Int return type but that would result in a type mismatch on line 9 since the expectation is Unit but the expression on that line is returning Int.

Default arguments
In Kotlin we can have default values when we define parameters. This provides flexibility and reduces boilerplate. Typically in Java we would use method overloading but in Kotlin that’s not necessary thanks to default arguments.

Example that uses default arguments

In the above example we provided a default value for the name parameter. The function was called twice, once with an argument and a second time without. This significantly reduces the boilerplate since we don’t need to use method overloading. It is advisable that default arguments, are always placed in the trailing position to avoid a compilation error.

This code will throw a compilation error

If we just swap the order of the parameters to move the parameter with the default value to a trailing position, then we no longer have a compilation error.

No compilation error because the default argument is in the trailing position

Named arguments
Sometimes in functions we have multiple parameters of the same type and at the time of calling the function it can be confusing what each argument was supposed to be.

some function with parameters of the same type

If we were to call this function, IntelliJ will show us the argument names.

IntelliJ showing parameter names

This is fine but if we wanted we could explicitly have the argument names. If we were to do so, it does not matter in which order we pass them.

Using named arguments

In the above picture we gave name to the arguments and we changed their order and there were no compilation errors. Named arguments brings more flexibility to Kotlin functions also combining named arguments with the default arguments I explained earlier makes functions even more flexible.

Varargs
The vararg keyword allows functions to receive a variable number of parameters.

If a function has more than one parameter, only one can use vararg

only one vararg is allowed

It is recommended to always use vararg in the trailing parameter. As oposed to Java where varargs (…) can be used only on the trailing parameter, in Kotlin we can use varargs in other order if we use a named argument. But yet it’s recommended to prefer the trailing parameter for for the vararg.

Using vararg in the first parameter is possible if we use named arguments

Spreading arrays with the spread operator
A vararg is not an array, it does not have a size. If we had a method that is expecting vararg, we cannot pass an array, that will throw a compilation error.

Type mismatch

So to this vararg we need to pass either 1 or many Int arguments. There’s a an operator in Kotlin called the spread operator (*), which allows us to spread the contents of an array into arguments that don’t accept arrays. All we need to do is just precede the argument with the ‘*’ operator.

spread operator used to pass IntArray to vararg of Int

Interestingly Kotlin language used the ‘*’ sign for the spread operator. This is also used in other languages such as SQL or UML to represent the many carnality.

Destructing arguments
Extracting values out of data classes can become very noisy See in this example where I am extracting the values out of a Triple which is a data class and I am just printing them in the console.

Boilerplate code to extract values out of data class

Well, we don’t have to do all that imperative fuzz to just take the values we want out of that Triple. Kotlin allows us to use it’s destructing feature to do this. Observe the next example.

So instead of giving a name to the variable we created a composed variable which is actually 3 variables wrapped into brackets. In line 4 we are calling each variable as if it were normal variables. The naming of the variable doesn’t matter, what matters is just the order in which we declare them. There’s also one more great possibility when we use destructing and that is, we don’t have to take everything is we don’t want. We can just take what we want, the only rule is that we mark with ‘_’ what we don’t want.

When destructing a data class we can cherry pick what we want

All we had to do is use an underscore (‘_’) where the postcode was supposed to go.

--

--

JAVING
JAVING

Written by JAVING

The present continuous form of “to program in Java”.

No responses yet