Question
How can a Kotlin function return three separate Int values—hour, minute, and second—in a single call, similar to a Swift function that returns (Int, Int, Int)?
func getTime() -> (Int, Int, Int) {
return (hour, minute, second)
}
Is there a Kotlin equivalent for returning multiple values without using an array or a map?
Short Answer
Kotlin functions return one value, but that value can be an object containing several values. For a fixed set of named values such as hour, minute, and second, a data class is usually the clearest solution. Kotlin also provides Pair and Triple for small, temporary groups of values, and supports destructuring to unpack them conveniently.
Concept
A Kotlin function has one return type. However, that return value may be an object that contains multiple pieces of data.
Swift supports tuple types such as (Int, Int, Int) directly. Kotlin does not provide general-purpose tuple types with arbitrary numbers of elements. Instead, Kotlin offers:
Pair<A, B>for exactly two values.Triple<A, B, C>for exactly three values.- A custom
data classfor named, meaningful values.
For time components, a data class is usually preferable because names make the result self-documenting:
data class TimeParts(
val hour: Int,
val minute: Int,
val second: Int
)
A caller can immediately see what each value means. In contrast, Triple<Int, Int, Int> exposes values as first, second, and third, which can be easy to mix up.
This matters in real programs because return values become part of your function's API. Clear names reduce bugs and make code easier to read, change, test, and maintain.
Mental Model
Think of a function's return value as one package it can hand back to its caller.
- A single
Intis a package containing one item. - A
Triple<Int, Int, Int>is a package containing three numbered compartments. - A
TimePartsdata class is a package with compartments clearly labelledhour,minute, andsecond.
All three values travel back from the function together, but Kotlin treats the package itself as the one returned value.
Syntax and Examples
Use a data class when the values have specific meanings.
data class TimeParts(
val hour: Int,
val minute: Int,
val second: Int
)
fun getTime(): TimeParts {
return TimeParts(hour = 14, minute = 30, second = 45)
}
fun main() {
val time = getTime()
println(time.hour) // 14
println(time.minute) // 30
println(time.second) // 45
}
The function returns one TimeParts object. That object stores the three Int values as named properties.
Kotlin also supports destructuring declarations for data classes:
val (hour, minute, second) = getTime()
println("$hour:$minute:$second") // 14:30:45
A data class automatically provides component functions for its constructor properties, allowing the destructuring syntax above.
For a quick, less descriptive option, use Triple:
fun getTime(): Triple<Int, Int, Int> {
return Triple(14, 30, 45)
}
val (hour, minute, second) = getTime()
Triple works, but use a data class when the returned values represent a real concept such as a time, coordinate, result, or validation outcome.
Step by Step Execution
Consider this code:
data class TimeParts(val hour: Int, val minute: Int, val second: Int)
fun getTime(): TimeParts {
return TimeParts(9, 5, 12)
}
fun main() {
val (hour, minute, second) = getTime()
println("$hour:$minute:$second")
}
Execution proceeds as follows:
TimePartsdefines an object with threeIntproperties.maincallsgetTime().getTime()createsTimeParts(9, 5, 12).- That one
TimePartsobject is returned tomain. - The destructuring declaration calls the data class's generated component functions:
hourreceives9minutereceives5secondreceives12
- The program prints:
9:5:12
If you wrote val time = getTime() instead, you would access the same values through time.hour, time.minute, and time.second.
Real World Use Cases
Returning a small value object is common when a calculation naturally produces related results:
- Parsing: return parsed
year,month, anddaycomponents. - Geometry: return a point with
xandycoordinates. - Statistics: return named values such as
minimum,maximum, andaverage. - Validation: return a status, error message, and optional normalized value.
- Pagination: return
items,nextPage, andtotalCountin a result model. - Image processing: return red, green, and blue color channels.
In each case, a data class gives the related values meaningful names and keeps them together.
Real Codebase Usage
In production Kotlin code, developers usually model related return values with a data class.
data class ParseResult(
val value: Int?,
val errorMessage: String?
)
fun parsePositiveInt(input: String): ParseResult {
val number = input.toIntOrNull()
?: return ParseResult(null, "Enter a whole number")
if (number <= 0) {
return ParseResult(null, "Number must be positive")
}
return ParseResult(number, null)
}
This example uses early returns for invalid input and returns a structured result in every case.
Common choices in a codebase:
- Use a data class for domain concepts and public APIs.
- Use
Pairfor a small, obvious two-value result in local code. - Use
Triplesparingly; unclearfirst,second, andthirdfields often indicate that a data class would be better. - Prefer existing domain types when available. For example, if you need an actual clock time rather than separate fields,
java.time.LocalTimemay be a better model on supported Kotlin platforms.
import java.time.LocalTime
fun getCurrentTime(): LocalTime = LocalTime.now()
LocalTime includes time-related behavior in addition to hour, minute, and second.
Common Mistakes
Expecting Kotlin to support Swift-style arbitrary tuples
This is not valid Kotlin syntax:
// Not valid Kotlin
fun getTime(): (Int, Int, Int) {
return (14, 30, 45)
}
Use Triple<Int, Int, Int> or, preferably, a data class.
Using Triple when names matter
fun getTime(): Triple<Int, Int, Int> = Triple(14, 30, 45)
val time = getTime()
println(time.second) // This is the second item: 30, not the seconds value
Triple.second means the second position, not a time's seconds field. Avoid this ambiguity with TimeParts.
Returning a mutable collection for a fixed structure
fun getTime(): MutableList<Int> = mutableListOf(14, 30, 45)
A mutable list allows callers to change or reorder values. A data class better represents a fixed result with known fields.
Forgetting to validate time values
If values come from user input or external data, verify their ranges:
require(hour in 0..23) { "Hour must be between 0 and 23" }
require(minute in 0..59) { "Minute must be between 0 and 59" }
require(second in 0..59) { "Second must be between 0 and 59" }
Destructuring in the wrong order
val (minute, hour, second) = getTime()
Destructuring is positional. Variable names do not change which property is assigned. Keep the declaration in the data class constructor order.
Comparisons
| Option | Best for | Access values as | Main limitation |
|---|---|---|---|
data class | Related values with clear meanings | time.hour or destructuring | Requires defining a type |
Pair | Two small, temporary values | first, second or destructuring | Only holds two values; names are generic |
Triple | Three quick, temporary values | first, second, third or destructuring | Generic names can be unclear |
List<Int> / IntArray | A variable-length sequence of same-kind values | Indexes such as [0] | Positions have no semantic names |
LocalTime | A real time-of-day value | time.hour, time.minute | Depends on the Java time API where applicable |
For hour, minute, and second:
// Clear and maintainable
data class TimeParts(val hour: Int, val minute: Int, val second: Int)
// Valid, but less expressive
Triple<Int, Int, Int>
Cheat Sheet
// Recommended: define named fields
data class TimeParts(val hour: Int, val minute: Int, val second: Int)
fun getTime(): TimeParts = TimeParts(14, 30, 45)
val time = getTime()
println(time.hour)
// Destructure a data class
val (hour, minute, second) = getTime()
// Built-in option for exactly three values
fun getTimeQuickly(): Triple<Int, Int, Int> = Triple(14, 30, 45)
val (hour, minute, second) = getTimeQuickly()
- Kotlin returns one value; that value may be an object holding many fields.
- Prefer a
data classwhen fields have names and meaning. Pairhasfirstandsecond.Triplehasfirst,second, andthird.- Destructuring assignment is positional.
- Use an array or list for a variable number of values, not a fixed named record.
FAQ
Can a Kotlin function return multiple values?
Yes. It returns one object that can contain multiple values. Use a data class, Pair, Triple, a collection, or an existing type.
Does Kotlin have tuples like Swift?
Kotlin has Pair and Triple, but it does not have general tuple types such as (Int, Int, Int, Int).
Should I use Triple or a data class in Kotlin?
Use Triple for short-lived, obvious local code. Use a data class when each value has a meaningful name or the result is part of a reusable function API.
How do I unpack a returned data class in Kotlin?
Use destructuring:
val (hour, minute, second) = getTime()
Can I return more than three values from Kotlin?
Yes, define a data class with as many properties as needed. A data class is preferable to nesting Pair or Triple objects.
Is IntArray a good replacement for three return values?
Only when the values are truly an ordered sequence. For hour, minute, and second, named properties are safer and clearer.
What is the best type for an actual time of day?
When available in your environment, java.time.LocalTime is often best because it represents a time of day and provides related operations.
Mini Project
Description
Create a small time parser that accepts a clock value in HH:MM:SS format and returns a named Kotlin object. This demonstrates returning multiple related values safely and validating external input before the rest of an application uses it.
Goal
Build a function that converts a valid time string into a TimeParts value and prints its separate components.
Requirements
Define a TimeParts data class with hour, minute, and second properties.
Create a function that accepts a time string in HH:MM:SS format.
Reject input that does not contain exactly three numeric components.
Reject values outside the ranges 0–23 for hours and 0–59 for minutes and seconds.
Use destructuring to print the parsed time components.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Add a Maven Repository URL in Gradle Kotlin DSL (build.gradle.kts)
Learn how to add Maven Central and a custom Maven repository URL in Gradle Kotlin DSL using build.gradle.kts syntax.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.