Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin when(Pair<>), is there any other way?

Tags:

I have a when construct that wants to match on two things:

when (activeRequest.verb to activeRequest.resourceType) {
    GET to "all" -> allGet()
    PUT to "foo" -> fooPut()
    GET to "foo" -> fooGet()
    POST to "bar" -> barPost()
    GET to "bar" -> barGet()
    COPY to "bar" -> barCopy()
    DELETE to "bar" -> barDelete()
    else -> logMismatch()
}

Is using the to pair constructor the only way to do this? It seems an odd use of Pair (though it works). I struggled to find it, because code fragments like

for ((key, value) in hashMap) {
    println("$key $value)
}

made me thing I should be able to do something similar in the when code, e.g.

when (activeRequest.verb, activeRequest.resourceType) {
    (GET, "all") -> allGet()
    (PUT, "foo") -> fooPut()
   ...
    else -> logMismatch()
}

While the pair works... what if I wanted to do 3 items?

like image 486
Travis Griggs Avatar asked Jul 12 '18 22:07

Travis Griggs


People also ask

How do I get data from kotlin pairs?

The kotlin pair will return with any number of values and also it accepts more than one return value at a time. Using data class it returns the values from the functions and using pair and tuple class also using array values for possible to return the pair values in kotlin.

How do you initialize a pair in Kotlin?

In Kotlin, constructor is a special member function that is invoked when an object of the class is created primarily to initialize variables or properties. To create a new instance of the Pair we use: Pair(first: A, second: B)

How do you create an array of pairs in Kotlin?

Just pass the pairs in the method indicating each pairs with their index number. The method makeSceneTransitionAnimation(Activity activity, Pair<View, String>... sharedElements) in the ActivityOptions class requires an activity as the first parameter and could have as many pairs as possible as the following parameter.

What is pair and triple Kotlin?

Kotlin provides a handy mechanism for representing two pieces of data in a single value: Pair . There is also Triple for representing three pieces of data.


1 Answers

The syntax in you for loop example is a destructuring declaration, which is basically syntactic sugar to declare references to multiple member variables of an object in one line. It doesn't go back the other way, as Kotlin doesn't have a mechanism for arbitrary tuples.

I can't really come up with a nice looking way to do this with more than two variables. The options I have on my mind are to either use an enum that basically works as a tuple like this:

enum class Response(val verb: String, val type: String) {

    GET_FOO("GET", "foo"),
    ...
    INVALID("?", "?");

    companion object {
        fun from(verb: String, type: String): Response {
            for(response in values()) {
                if(response.verb == verb && response.type == type)
                    return response
            }

            return INVALID
        }
    }
}

when(Response.from(activeRequest.verb, activeRequest.resourceType)) {
    GET_FOO -> getFoo()
    ...
}

Or to use arrays. Unfortunately, Kotlin array equality is not by contents, so you end up with a lot of boilerplate, and when syntax stops looking very good. (I added an extension function to make this a little better, but I still don't love it):

fun Array<*>.whenCheat(vararg others: Any?): Boolean {
    return this contentEquals others
}

val array = arrayOf("GET", "foo")
when {
   array.whenCheat("GET", "foo") -> getFoo()
   ...
}

My suspicion is that this kind of thing would be better served by a map of responses to functions. Hopefully someone else comes by with a more clever solution.

like image 200
emerssso Avatar answered Oct 14 '22 05:10

emerssso