- Kotlin Function Return Multiple Values (Tuple)
- Data Class
- How to return multiple values from a function in kotlin like we do in swift in Android?
- Method 1: Using a Pair or Triple
- Method 2: Using a Data Class
- Method 3: Using a List or Array
- Method 4: Using a Tuple
- Method 5: Using a custom class
- Conclusion
- Functions
- Default arguments
- Named arguments
- Unit-returning functions
- Single-expression functions
- Explicit return types
- Variable number of arguments (varargs)
- Infix notation
- Function scope
- Local functions
- Member functions
- Generic functions
- Tail recursive functions
Kotlin Function Return Multiple Values (Tuple)
NOTE: Max 5 deconstructed variables. If you try to deconstruct into 6 variables, you shall bump into Destructuring declaration initializer of type Array must have a ‘component6()’ function .
Data Class
data class Result(val index: Int, val name: String, val isActive: Boolean, val score: Double, val item5: String?, val item6: String?) fun returnDataClass() = Result(1, "Desmond", true, 9.0, null, "item6")
val (index: Int, name, isActive, score, _, item6) = returnDataClass()
NOTE: Destructuring variables type is cast correctly.
NOTE: More than 5 deconstructed variables.
❤️ Is this article helpful?
Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.
Do send some 💖 to @d_luaz or share this article.
A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz
Travelopy — discover travel places in Malaysia, Singapore, Taiwan, Japan.
How to return multiple values from a function in kotlin like we do in swift in Android?
In Kotlin, there are several ways to return multiple values from a function. Here are a few methods:
Method 1: Using a Pair or Triple
- Step 1 — Declare a function that returns a Pair or Triple, depending on the number of values you want to return.
For example, if you want to return two values, you can use the Pair class, and if you want to return three values, you can use the Triple class. Here is an example of a function that returns a Pair of two Int values:
fun getTwoValues(): PairInt, Int> val value1 = 5 val value2 = 10 return Pair(value1, value2) >
val (firstValue, secondValue) = getTwoValues()
Method 2: Using a Data Class
Here is an example of a data class that holds two Int values:
data class TwoValues(val value1: Int, val value2: Int)
Here is an example of a function that returns an instance of the TwoValues class:
fun getTwoValues(): TwoValues return TwoValues(5, 10) >
val values = getTwoValues() val firstValue = values.value1 val secondValue = values.value2
Method 3: Using a List or Array
Here is an example of a function that returns a List of Int values:
fun getTwoValues(): ListInt> return listOf(5, 10) >
val values = getTwoValues() val firstValue = values[0] val secondValue = values[1]
In all of the above methods, you can return more values by adding more variables inside the Pair/Triple, Data class or List/Array.
It is important to note that all of these methods are used to return multiple values from a function, but they each have different use cases. For example, if you want to return two or three values that are related, you should use the Pair or Triple classes. If you want to return multiple values that are related and have meaningful names, you should use a data class. And if you want to return multiple values that have no relationship and have no meaningful names, you should use a List or Array.
Method 4: Using a Tuple
- Step 1 — Kotlin does not have a built-in Tuple class, but you can use a third-party library such as Arrow to use Tuple classes
To use the Tuple class from Arrow, you need to add the following dependency in your build.gradle file:
implementation "io.arrow-kt:arrow-core:$arrow_version"
- Step 2 — Declare a function that returns a Tuple, depending on the number of values you want to return
Here is an example of a function that returns a Tuple of two Int values:
import arrow.core.Tuple2 fun getTwoValues(): Tuple2Int, Int> return Tuple2(5, 10) >
- Step 3 — Call the function and access the values using the first and second properties of the Tuple class.
val values = getTwoValues() val firstValue = values.a val secondValue = values.b
Method 5: Using a custom class
Here is an example of a custom class that holds two Int values:
class TwoValues(val value1: Int, val value2: Int)
Here is an example of a function that returns an instance of the TwoValues class:
fun getTwoValues(): TwoValues return TwoValues(5, 10) >
val values = getTwoValues() val firstValue = values.value1 val secondValue = values.value2
Conclusion
In conclusion, returning multiple values from a function in Kotlin can be done in several ways. You can use the Pair or Triple classes, a data class, a List or Array, a Tuple class from a third-party library, or a custom class. Each method has its own use case and advantages, and it’s important to choose the one that best suits your requirements. It’s also important to understand the concepts behind each method and how they work. I hope this tutorial has provided you with a good understanding of how to return multiple values from a function in Kotlin and has given you the knowledge to make the right choice for your project.
Functions
Function parameters are defined using Pascal notation — name: type. Parameters are separated using commas, and each parameter must be explicitly typed:
You can use a trailing comma when you declare function parameters:
Default arguments
Function parameters can have default values, which are used when you skip the corresponding argument. This reduces the number of overloads:
A default value is set by appending = to the type.
Overriding methods always use the base method’s default parameter values. When overriding a method that has default parameter values, the default parameter values must be omitted from the signature:
If a default parameter precedes a parameter with no default value, the default value can only be used by calling the function with named arguments:
If the last argument after default parameters is a lambda, you can pass it either as a named argument or outside the parentheses:
fun foo( bar: Int = 0, baz: Int = 1, qux: () -> Unit, ) < /*. */ >foo(1) < println("hello") >// Uses the default value baz = 1 foo(qux = < println("hello") >) // Uses both default values bar = 0 and baz = 1 foo < println("hello") >// Uses both default values bar = 0 and baz = 1
Named arguments
You can name one or more of a function’s arguments when calling it. This can be helpful when a function has many arguments and it’s difficult to associate a value with an argument, especially if it’s a boolean or null value.
When you use named arguments in a function call, you can freely change the order that they are listed in. If you want to use their default values, you can just leave these arguments out altogether.
Consider the reformat() function, which has 4 arguments with default values.
fun reformat( str: String, normalizeCase: Boolean = true, upperCaseFirstLetter: Boolean = true, divideByCamelHumps: Boolean = false, wordSeparator: Char = ‘ ‘, ) < /*. */ >
When calling this function, you don’t have to name all its arguments:
You can skip all the ones with default values:
You are also able to skip specific arguments with default values, rather than omitting them all. However, after the first skipped argument, you must name all subsequent arguments:
You can pass a variable number of arguments ( vararg ) with names using the spread operator:
When calling Java functions on the JVM, you can’t use the named argument syntax because Java bytecode does not always preserve the names of function parameters.
Unit-returning functions
If a function does not return a useful value, its return type is Unit . Unit is a type with only one value — Unit . This value does not have to be returned explicitly:
The Unit return type declaration is also optional. The above code is equivalent to:
Single-expression functions
When the function body consists of a single expression, the curly braces can be omitted and the body specified after an = symbol:
Explicitly declaring the return type is optional when this can be inferred by the compiler:
Explicit return types
Functions with block body must always specify return types explicitly, unless it’s intended for them to return Unit , in which case specifying the return type is optional.
Kotlin does not infer return types for functions with block bodies because such functions may have complex control flow in the body, and the return type will be non-obvious to the reader (and sometimes even for the compiler).
Variable number of arguments (varargs)
You can mark a parameter of a function (usually the last one) with the vararg modifier:
In this case, you can pass a variable number of arguments to the function:
Inside a function, a vararg -parameter of type T is visible as an array of T , as in the example above, where the ts variable has type Array .
Only one parameter can be marked as vararg . If a vararg parameter is not the last one in the list, values for the subsequent parameters can be passed using named argument syntax, or, if the parameter has a function type, by passing a lambda outside the parentheses.
When you call a vararg -function, you can pass arguments individually, for example asList(1, 2, 3) . If you already have an array and want to pass its contents to the function, use the spread operator (prefix the array with * ):
If you want to pass a primitive type array into vararg , you need to convert it to a regular (typed) array using the toTypedArray() function:
val a = intArrayOf(1, 2, 3) // IntArray is a primitive type array val list = asList(-1, 0, *a.toTypedArray(), 4)
Infix notation
Functions marked with the infix keyword can also be called using the infix notation (omitting the dot and the parentheses for the call). Infix functions must meet the following requirements:
- They must be member functions or extension functions.
- They must have a single parameter.
- The parameter must not accept variable number of arguments and must have no default value.
infix fun Int.shl(x: Int): Int < . >// calling the function using the infix notation 1 shl 2 // is the same as 1.shl(2)
Infix function calls have lower precedence than arithmetic operators, type casts, and the rangeTo operator. The following expressions are equivalent:
- 1 shl 2 + 3 is equivalent to 1 shl (2 + 3)
- 0 until n * 2 is equivalent to 0 until (n * 2)
- xs union ys as Set is equivalent to xs union (ys as Set)
On the other hand, an infix function call’s precedence is higher than that of the boolean operators && and || , is — and in -checks, and some other operators. These expressions are equivalent as well:
Note that infix functions always require both the receiver and the parameter to be specified. When you’re calling a method on the current receiver using the infix notation, use this explicitly. This is required to ensure unambiguous parsing.
Function scope
Kotlin functions can be declared at the top level in a file, meaning you do not need to create a class to hold a function, which you are required to do in languages such as Java, C#, and Scala (top level definition is available since Scala 3). In addition to top level functions, Kotlin functions can also be declared locally as member functions and extension functions.
Local functions
Kotlin supports local functions, which are functions inside other functions:
A local function can access local variables of outer functions (the closure). In the case above, visited can be a local variable:
Member functions
A member function is a function that is defined inside a class or object:
Member functions are called with dot notation:
For more information on classes and overriding members see Classes and Inheritance.
Generic functions
Functions can have generic parameters, which are specified using angle brackets before the function name:
For more information on generic functions, see Generics.
Tail recursive functions
Kotlin supports a style of functional programming known as tail recursion. For some algorithms that would normally use loops, you can use a recursive function instead without the risk of stack overflow. When a function is marked with the tailrec modifier and meets the required formal conditions, the compiler optimizes out the recursion, leaving behind a fast and efficient loop based version instead:
val eps = 1E-10 // «good enough», could be 10^-15 tailrec fun findFixPoint(x: Double = 1.0): Double = if (Math.abs(x — Math.cos(x)) < eps) x else findFixPoint(Math.cos(x))
This code calculates the fixpoint of cosine, which is a mathematical constant. It simply calls Math.cos repeatedly starting at 1.0 until the result no longer changes, yielding a result of 0.7390851332151611 for the specified eps precision. The resulting code is equivalent to this more traditional style:
To be eligible for the tailrec modifier, a function must call itself as the last operation it performs. You cannot use tail recursion when there is more code after the recursive call, within try / catch / finally blocks, or on open functions. Currently, tail recursion is supported by Kotlin for the JVM and Kotlin/Native.