tl;dr We understand that a number of use cases related to bit-fiddling/hex number are painful in Kotlin, and we are working on it, but it’s a bit more complicated than one might think, and that’s why it’s taking us so much time.
Kotlin 1.1 will ship a (small) number of new bitwise operations in the Standard Library, namely and
/ or
/ xor
/ inv
for Byte
and Short
. These may seem straightforward wrt API design: byte bitwise-or another byte gives a byte, right? But we moved these functions to kotlin.experimental
package, which means that we are not sure that this API will remain this way. This package is not imported by default, so you’ll need to import it in order to use these operations:
import kotlin.experimental.*
Don’t get me wrong: Kotlin will have bitwise operations for all necessary types (Int
s and Long
s are already covered, so it’s mostly Byte
s and Short
s we are talking about here), we just don’t know whether it’s right to have them return Byte
/Short
or Int
.
Why we can’t decide just now
The problem with this particular case (and
/or
/xor
/inv
) is that it’s only the top of a fairly large iceberg. There are following interconnected things that have to be added to Kotlin at some point, but we can only design them all together:
- bitwise operations
- unsigned numeric types (
UByte
,UShort
,UInt
,ULong
) - large hexadecimal constants (
0xFFFFFFFF
) - (surprise) value types
The current master plan is:
- implement unsigned numeric types as value types (represented as signed numbers under the hood)
- have large hex constants have unsigned types (i.e.
0xFFFFFFFF
is not a negative Int, but an unsigned Int, i.e.UInt
) - bitwise operations must be available on both signed and unsigned types (and on unsigned types, shifts are almost straightforward)
And this is a really big hunk of language design, even if we leave out the value types part (we could probably roll out an ad hoc implementation of unsigned types, and later transparently re-implement them as value types). So, we just haven’t finished it yet. And, trust me, it’s all interconnected, i.e. we can’t be sure we know the API for bitwise operations before we have finalized the design of unsigned types.
Hence the kotlin.experimental
package.
Workarounds for now
Back to bit-fiddling alone (all following does not speak about unsigned types or hex constants).
The best way that I can see for now is having a separate library for bitwise operations. Inline functions will make it fairly performant (there will be a bit more byte code than in straightforward translation, but that will be fixed at some point by the compiler getting smarter). Anyone can write such a library defining operations like
infix inline fun Byte.shl(shift: Int): Int = this.toInt() shl shift
And so on. You can choose to return Byte
, if that fits your use cases better. You can even draw all of Hacker’s delight in as library functions (which strikes me as a great exercise, btw :)).
If at some point there is such a library (or even many of them), we’ll definitely consult its design while making our decisions.
Sorry for the temporary inconvenience, and have a nice Kotlin!