seems a bug : ``` val min = (1u shl 10) + 1...
# getting-started
c
seems a bug :
Copy code
val min = (1u shl 10) + 1u
        val max = (1u shl 16) - 1u
        return port in min as Int..max as Int
range must use Int instead of UInt
y
Weird. UIntRange is a thing. Could
port
maybe be an Int, and that's why you get an error? Also what version of Kotlin are you using?
e
if
port
is an
Int
, then do it the other way around:
Copy code
port.toUInt() in min..max
1
k
It's not a bug. The reason for the ClassCastException being thrown has nothing to do with ranges. It's just this:
Copy code
min as Int
You can't do this, because
min
is not an
Int
. It's a
UInt
. The same would happen if
min
was a
Long
. If you want to turn it into an
Int
, you need to do
min.toInt()
.
c
but you cannot use
port in min..max
.
k
You can use
port in min.toInt()..max.toInt()
On the other hand, why don't you just define them as
Int
in the first place? They don't go negative since they don't get anywhere close to the most significant bit.
Copy code
val min = (1 shl 10) + 1
    val max = (1 shl 16) - 1
    return port in min..max
c
but port numbers are UINT16
why UINT16s have no range?
k
But UINT16 is
UShort
in Kotlin, whereas you're using
UInt
.
If you really want to use UINT16 (even though Int is sufficient and less hassle to work with) then you can do this:
Copy code
fun portIsValid(port: UShort): Boolean {
    val min = ((1u shl 10) + 1u).toUShort()
    val max = ((1u shl 16) - 1u).toUShort()
    return port in min..max
}
You might want to consider doing this for greater type safety:
Copy code
@JvmInline
    value class PortNumber(val value: UShort) {
        constructor(value: Int) : this(validate(value))
        companion object {
            fun validate(value: Int): UShort {
                require(value in 0..65535) { "Port number $value outside of valid range." }
                return value.toUShort()
            }
        }
    }

    fun isValid(port: PortNumber): Boolean {
        val min = PortNumber((1 shl 10) + 1)
        val max = PortNumber((1 shl 16) - 1)
        return port in min..max
    }
c
but shorts are int number too.
long, int, short, byte are all int number types
as I have tested.
Copy code
var a : ULong = 1u
        var b: ULong = 10u
        var c: ULong = 3u
        if(c in a..b)  {
            println("true")
        } else {
                        println("false")

        }
this code works
as document implies in https://kotlinlang.org/docs/basic-types.html
Copy code
they are all types of number
It valids that the rang operator not supporting all these types is a bug and should be fixed in later versions.
e
integer types are not automatically convertible, nor should they be
c
It is not about type conversion, it is about range support within numbers.
O no, they are automatically converted.
UShort to Int
UShort rang is supported
e
Kotlin doesn't let you write
Copy code
min <= port && port <= max
or
Copy code
port in listOf(min, max)
with different signed/unsigned types, so why should
Copy code
port in min..max
be any different?
c
Copy code
var a : UShort = 1u
        var b: UShort = 10u
        var c: UShort = 3u
        if(c in a..b)  {
            println("true")
        } else {
                        println("false")

        }
this code works
the problem is kotlin auto covert ushort into int.😀
I didn't notice that.
through computing..
Copy code
fun port(port: UShort): Boolean {
            val min:UInt = (1u shl 10) + 1u
            val max:UInt = (1u shl 16) - 1u
            return port in min..max
        }
e
none of the range types smaller than
Int
exist
c
it does exist.
I just tested here.
all number types should works
e
https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.ranges/contains.html has some reasonable conversions, so you can check narrower types in wider ranges
c
Then it is a preblem
e
but Int in UIntRange is neither narrower nor wider
c
Should be a Range<T>
e
oh and generics cause all values to be boxed, great idea
there is a ClosedRange type but the specific integer ranges avoid boxing
c
Convert all types into Int is also a great idea.
e
I meant that sarcastically.
of course that's a terrible idea
c
I meant that too.
😀
UShortRange, ULongRange, UByteRange, UIntRange.
It is very simple to create them, why not?
For a range, It can be in eight types. (U)ByteRange, (U)ShortRange, (U)IntRange, (U)LongRange。 nothing more.
e
on JVM, there are really only two integer primitive types: Int and Long. primitive Byte and Short only exist in the type system, at runtime they are simply Int
c
Every simple.
e
UIntRange and ULongRange exist. there are no operations on UShortRange and UByteRange which would work any differently than UIntRange.
c
what difference between them? Why should range operator break the integraty of number types in kotlin?
it seems
shl
has the same problem only works on some types of number types.
to keep port computed in an integrated matter, I did my best to developed this code:
Copy code
fun port(port: UShort): Boolean {
            val min:UShort = ((1u shl 10) + 1u).toUShort()
            val max:UShort = ((1u shl 16) - 1u).toUShort()
            return port in min..max
        }
e
similarly, as far as the underlying platform goes, only
ishl
ishr
iushr
lshl
lshr
lushr
exist. narrower shifts do not exist.
c
my suggestion to add support to other numbers:)
e
you'll note that Byte and Short arithmetic always upcast to Int, same as Java
UByte and UShort upcasting to UInt is consistent
c
but the operation does exist when it comes to some kind hardwares
e
barely. such operations exist on x86 due to historical compatibility but they are no faster than 32-bit arithmetic. they do not exist on ARM.
c
I don't think so. Currently minimum transferring/storing unit is byte. We will always has some thing to do with byte and sometimes short.
y
Sure, but addressing-wise, everyone is dealing with 32-bit minimum. Literally going lower doesn't make you go any faster because we've optimised for 32-bit
e
memory busses are 32-bits wide at a minimum, you're never transferring only 8 bits
c
Your can optimize it, but not to ignore it.
It is obvious most cpus are 64 bit wide now. Then we should drop Int to support Long only
e
if you are only targeting modern processors, sure. but Kotlin's primary target is JVM which was designed during the 32-bit era, and Kotlin's other targets include JS which can only handle bitwise arithmetic up to 32-bit, and several 32-bit native architectures
c
js donnot have byte type.
If you don't introduce Byte Type or Short Type, Then no one will complain that, But You have such types.
Then you should keep such consistency.
e
can't have Java compatibility without having the same set of numeric types as Java
Java has Byte and Short even if JVM stack and registers and instructions are only Int and Long
c
does java have range?
Byte and Short have nothing to do with jvm.
e
I see no reason to continue this conversation if you're going to be facetious.
c
You can place Int and Long in byte codes.
But you should keep Byte and Short operation in a integrated way.
Logic correctness and competency are very important features to a language.
I hope I can see such competency in new versions. 😀