:thinking_face:
# announcements
f
🤔
it
is a
ByteArray
This fixes it but the reason why I have to call the conversion only for that particular number is beyond me.
s
Bytes are signed
f
I see, still, seems rather arbitrary.
s
ie. 0x80 is 128 which cannot fit into a signed byte which has a max value of 127.
f
I understood but it's still rather arbitrary why one has to manually transfrom those but not the others. It is in general a pain to work on such a low level with Kotlin I'm afraid.
m
Hmm, it's not really arbitrary that the number is out of range? Kotlin is pretty consistent in that it doesn't perform any implicit conversions between the number-types.
f
The inconsistency that I see is that
0x80
is reported as integer literal whereas
0x00
is considered a byte literal. How come? Why is
0x00
not considered an integer literal?
The inconsistency continues with
0.toByte()
,
0.toShort()
,
0
, and
0L
. 😛
d
0x00
can be both an integer or byte (or short) literal.
0x80
can only be an integer because it's not a valid byte.
Copy code
val x: Int = 0x00 // valid
val y: Byte = 0x00 // valid
val z: Int = 0x80 // valid
val w: Byte = 0x80 // invalid, not a byte.
f
So it does implicit conversion. 😉
That's my whole point here.
d
No, it does not convert.
0x00
has different types, depending on context.
Once it's inferred to be an Int, it stays an int, unless you explicitly convert.
f
Which means its type is converted based on context.
d
It is not converted.
Conversion implies it is first one type and then another.
4
val x: Byte = 0x00
does not do any conversion. It simply "creates" a byte.
f
Technically correct yes, it still seems arbitrary and I would clearly prefer it to be more consistent and strict with this.
d
Again, what's arbitrary?
g
It’s the same as other types:
Copy code
val b: Int = 1
val a: Long = 1
f
Prints
0
Rust:
error[E0277]: cannot subtract i64 from i32
g
That’s because there is a
operator fun minus
defined for
Int
that accepts
Long
👆 2
d
-
is overloaded in Kotlin to allow
Int.minus(Long)
. It returns a
Long
. It's perfectly reasonable, imho.
You can even click on the
-
to jump to the definition.
f
That is reasonable, yes. I'm still disappointed. Here the type is correctly inferred by Rust and that's what I would expect from Kotlin.
d
I am not familiar with Rust, but I'd assume that those are unsigned bytes?
k
u8 seems unsigned
f
u8
is unsigned but
0x80
does not carry that info.
k
no
0x80
is inferred to be an
u8
out of context
d
buf[6]
is unsigned.
buf[6] & 0x0f
is therefor also unsigned.
f
In Kotlin (see screenshot above) I have to place the
u
after each literal.
d
Now we are getting somethere. That is a valid bug report.
k
Cause unsigned types are experimental
f
But I have opted in, that's not a real excuse imho.
k
I think they want the explicit opt-in atm
f
@ExperimentalUnsignedTypes
how much more explicit?
t
@Fleshgrinder just out of curiosity, why do you need to be so low level ? Just wondering but I never need to handle byte shifting so I'm wondering in what kind of context you'd need this.
f
The code above is for UUIDv5 (SHA-1) and I'm setting the version to 5 (first line) and the variant to RFC 4122 (second line).
t
ok thanks
f
🙂
d
This is because hex literals in kotlin are always signed (which in my opinion is horrible), the byte literal for
0x80
is
-0x80
f
🤝
😞
k
I think that's also an issue with normal ints and bytes
g
Hex literals are always signed because there are no unsigned types in Kotlin before 1.3 (and even now they are experimental), same as in Java (and JS)