Blog Post

Pairs and Triples in Kotlin (And Why You Shouldn't Use Them)

Illustration: Pairs and Triples in Kotlin (And Why You Shouldn't Use Them)

Kotlin’s sugar coating is great, but too much sugar can seriously hurt your health. In this blog post, we’ll discuss just that: why pairs and triples in Kotlin are an anti-pattern, and why you shouldn’t use them.

Using Pairs and Triples

Let’s say you have a form to collect the first and last name of a user, and you need to pass them to another screen. A convenient way would be to create a Pair:

val user : Pair<String, String> = Pair("John", "Doe")

What if you want to collect and pass the user’s age as well? You could use a Triple instead of a Pair:

val user : Triple<String, String, Int> = Triple("John", "Doe", 20)

Simple, right? This is where the convenience ends, for several reasons. First, if you’re passing this to another screen, it’s easy to get confused about what these properties mean. Take a look at the following example:

if(user.third > 21) {
  setEligible(user.first, user.second)
}

If you were to see this chunk of code without previous knowledge of how the Triple was created, you could easily be confused with its meaning. What is user.third and why should it be over 21? What are user.first and user.second, and why are they parameters for the setEligible() function? Pairs and triples are easy to write, but they’re often confusing to read and later interpret. This is always a red flag that something should be changed in the code.

This is also where your expandability possibilities end — there’s no Quadruple or anything of that sort. If you want to add another property, you’d have to create your own data class. Or if you’re too lazy, you could go with a more radical solution, such as Triple<Pair, Int, String> (where the pair contains the first and last name), which would make things even more confusing:

if(user.second > 21) {
  setEligible(user.first.first, user.first.second)
}

So if pairs and triples are problematic, why do we use them?

Pairs and Triples Under the Hood

We create pairs and triples because we want to avoid creating our own data classes. But let’s dig into the Tuples.kt class, which provides the implementation of Pair and Triple, to see what they really are:

public data class Pair<out A, out B>(
    public val first: A,
    public val second: B
)

(...)

public data class Triple<out A, out B, out C>(
    public val first: A,
    public val second: B,
    public val third: C
)

We avoid writing data classes and instead write… data classes?

Pair is just a data class

Conclusion

Pair and Triple are just data classes that are (arguably) more convenient than making our own data class, but there’s not much sense in using them. Although there’s nothing wrong with how Pair and Triple work, they violate the O in SOLID, in that they’re not open for extension. Additionally, they confuse code reviewers, and they could possibly even confuse future-you. Yes, making a completely new data class does take more time, but it contributes to improved code readability.

Explore related topics

Related products
Share post
Free trial Ready to get started?
Free trial