I love such an idiom in Rust:
# stdlib
m
I love such an idiom in Rust:
I propose adding similar thing to Kotlin e. g. this way:
Copy code
inline fun <C : Comparable<C>, R> C.cmpFold(
        other: C,
        ifLess: () -> R,
        ifEqual: () -> R,
        ifGreater: () -> R
): R {
    val cmp = this.compareTo(other)
    return when {
        cmp < 0 -> ifLess()
        cmp == 0 -> ifEqual()
        cmp > 0 -> ifGreater()
        else -> throw AssertionError()
    }
}
use sample: `
Copy code
println(a.cmpFold(b, ifLess = { "<" }, ifEqual = { "=" }, ifGreater = { ">" }))
s
that like saves me no typing though
if you wanted to actually add this to the stdlib, why wouldn’t you just mirror the rust approach more closely by providing an
Ordering
enum and adding an extension function that returns it?
☝🏼 1
using the values with
when
looks more idiomatic, is more flexible, and avoids having to call a function with three lambdas lol
Copy code
enum class Ordering {
  Greater, Less, Equal
}

fun <T : Comparable<T>> T.compareMatch(other: T): Ordering = when (compareTo(other)) {
  1 -> Ordering.Greater
  0 -> Ordering.Equal
  else -> Ordering.Less
  // or to be *absolutely* sure
  // -1 -> Ordering.Less
  // else -> throw IllegalStateException("compareTo returned out of spec value")
}

fun test(a: Int, b: Int) {
  when (a.compareMatch(b)) {
    Ordering.Greater -> println("greater!")
    Ordering.Equal -> println("equal!")
    Ordering.Less -> println("less!")
  }
}
m
I see no problem in passing three lambdas. It's free; having an extra enum is not.
compareTo
is free to return any int. Your example, fixed:
Math.sign(compareTo(other))
d
I would prefer this syntax:
Copy code
when (a.compareTo(b)) {
    > 0 -> ...
    0 -> ...
    < 0 -> ...
}
This would require adding
>
and
<
to allowed operations for
when
cases, and knowing that these conditions are exhaustive, but it would work.
s
It’s free; having an extra enum is not.
oh no, a whole extra enum 😱😱
Your example, fixed
uh thanks, don’t think
Math.sign()
is on the jvm, but we could just check if the value is greater or less than 0
j
It's
signum
and it's only for floating-point-based types.
s
That’d do it
d
There's
Int.sign
(https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.math/sign.html), though it would be nice if the restricted return values of -1, 0, and 1 were part of the method's signature so that you could restrict a
when
to those three values.
m
oh no, a whole extra enum 😱😱
well, yes, a whole extra class which must be loaded, verified and compiled. For example, some stdlib internals use
typealias ... = Int
and `const val`s as 'free enums'.
j
you're either using an optimizer in which case an enum is free or you're not using one in which case a single enum doesn't matter
a
I think if Kotlin wouldn't depend on Java or if Java 1.0 already had enums it would be similar to Rust in this regard. Being Java compatible (which is probably Kotlin's best feature) brings a few drawbacks such as this weird comparison integer instead of an enum. I think writing the following isn't too bad. It might be less efficient because it calls the comparator twice, but I feel like it is very readable.
Copy code
when {
    a > b -> "greater"
    a < b -> "less"
    else -> "even"
}
I would prefer an enum over integers as comparison results. But having two concepts in the stdlib would be very confusing imho. Another possibility could be to replace the comparator results with an enum/sealed class that magically inherits from
Int
. But I guess that would need some compiler magic and deep feasability investigation and I don't think it's worth the effort.
c
@Astronaut4449 how much Java 1.0 are you seeing out there?
a
@Cody Engel What I meant is that those integer comparators are from a time before enums and we're stuck with them now.
🙇🏻‍♂️ 1