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?
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.
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)
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With