would it be feasible to have a `Range` on enums?
# stdlib
e
would it be feasible to have a
Range
on enums?
s
Yes, enums are comparable so you can make a range using the usual operators/functions. The sort order is based on the order the enum entries appear in the source code, so caution is needed, especially around API compatibility.
e
I'm asking about a ready to have in stdlib
s
Can you give an example of the kind of thing you want?
e
https://gist.github.com/elect86/d659ab70e47c7ca9c372c15fb1ce05b2
isGamepad
can become
this in Gamepad_BEGIN until Gamepad_END
I have the same case over and over again
c
Copy code
enum class Test {
    A,
    B,
    C,
    ;
}

println(Test.A.ordinal in Test.B.ordinal until Test.C.ordinal)
?
e
that's exactly what I'm using, I'd love to skip
.ordinal
s
It’s possible, but only with
..
, not with
until
.
At the moment,
until
only works for integral types, because
a until b
is basically implemented as
a..(b - 1)
. It doesn’t work for enum types because they don’t have addition and subtraction 😄.
1
e
well, that could be another nice feature to have, enumA + 1, to get the next one
s
But open ranges for other types are coming!
c
Copy code
enum class Test {
    A,
    B,
    C,
    ;
}

infix fun Test.until(end: Test) = this..(enumValues<Test>()[end.ordinal-1])

println(Test.B in Test.A..Test.B)
println(Test.B in Test.A until Test.B)
You'll have to add a check for if
end
is the first element of the enum, but you get the idea
s
For now, I would just recommend that you change your code to
Copy code
val Gamepad_BEGIN = GamepadStart
val Gamepad_END = GamepadRStickDown

val isGamepad: Boolean
   get() = this in Gamepad_BEGIN..Gamepad_END
(so that the
Gamepad_END
boundary is inclusive rather than exclusive)
e
I thought about that, but since it's a port from native, maintenance comes first
s
The feature you want is coming, it’s just experimental

https://www.youtube.com/watch?v=v0AHdAIBnbs

👀 1
a
you could also try using multiple sealed-interfaces
Copy code
sealed interface Key {
  enum class Keyboard : Key { A, B, C, ... } 
  enum class Gamepad: Key { Start, Back, Left, ... }
}
Then you can check using
is
Copy code
fun checkKey(key: Key) {
  when (key) {
    is Gamepad -> {}
    is Key -> {}
  }
}
Or, if you want to keep the keys ‘flat’ and not nested, and if you want the keys to have multiple ‘types’, use objects instead of enums.
Copy code
sealed interface Key {
  sealed interface Keyboard: Key
  sealed interface Gamepad: Key

  sealed interface DirectionKey: Key

  object A: Keyboard, DirectionKey
  object B: Keyboard
  object C: Keyboard
  //...
  object W: Keyboard, DirectionKey
  object S: Keyboard, DirectionKey
  object D: Keyboard, DirectionKey

  object GamepadLeft: Gamepad, DirectionKey
  object GamepadRight: Gamepad, DirectionKey
}
Just throwing out ideas - it might be overkill and too complicated!
e
overkill, but nice idea