I'm kind of frustrated for having to use a custom ...
# language-evolution
e
I'm kind of frustrated for having to use a custom lib for unsigned because inline classes cannot extend other classes (ie
Number
). So I was thinking, maybe we can have inline classes exposes/extends/delegates specific interfaces/classes from the underlying value.. something like
inline class UInt(val i: Int) : Number by i
e
https://youtrack.jetbrains.com/issue/KT-27435 but Number is a fairly useless class to implement, plus Int's implementation will be wrong for all the widening conversions
e
damn, thanks
e
note that if you have a
Copy code
val foo: Number = 1u
then
foo
will be a real object of type
kotlin.UInt
, "boxed" just like
val foo: Number = 1
will be a boxed Integer, not a primitive. there's very few reasons to use Number
e
I need extension on
Number
for base type such as this
e
just take the Number constraint out
e
tempting
because that'd play nice with `Boolean`s as well
e
the only useful functions are on specific types anyway
possibly go the stdlib route and generate specific types, a la
IntArray
,
UIntArray
, etc.
e
I'm gonna try that
e
https://github.com/ephemient/kotlin-numeric is a simple project that has auto-generated
IntPair
,
UIntPair
, etc.
👍 1
e
dropping the
Number
constraint means I cannot longer use these for unsigned
I hope they implement that feature asap
e
I don't think that's a reasonable constructor anyway
e
it's useful when you want to convert one type to another one
j
Number is misleading, but T:Comparable<T> does get a job done. for network addressing i sort of baked a paeno numbers hack to operate on arbitrary bit lengths without resorting to BitSets. like everything else that touches primitives, there are boilerplate impl classes not shown
Copy code
interface BitOps<Primitive : Comparable<Primitive>> {
    val one: Primitive
    val shl: (Primitive, Int) -> Primitive
    val shr: (Primitive, Int) -> Primitive
    val xor: (Primitive, Primitive) -> Primitive
    val and: (Primitive, Primitive) -> Primitive
    val or: (Primitive, Primitive) -> Primitive
    val plus: (Primitive, Primitive) -> Primitive
    val minus: (Primitive, Primitive) -> Primitive
    fun toNumber(x: Primitive): Number = x.let {
        when (one) {
            is Number -> it as Number
            is UByte -> (it as UByte).toInt()
            is UShort -> (it as UShort).toInt()
            is UInt -> (it as UInt).toLong()
            else -> (it).toString().toBigInteger()
        }
    }



    companion object {
       /**
         * minimum bitops types for the intended bitcount of NUID
         */
        fun minOps(size: Int): BitOps<*> = when (size) {
            in Int.MIN_VALUE..7 -> ByteBitOps
            8 -> UByteBitOps
            in 9..15 -> ShortBitOps
            16 -> UShortBitOps
            in 17..31 -> IntBitOps
            32 -> UIntBitOps
            in 33..63 -> LongBitOps
            64 -> ULongBitOps
            else -> BigIntOps
        }
    }
}
some amount of credit to @ephemient Numeric as well but no overlap
i hadn't considered 1 bit numbers for Boolean here, but nothing stopping it.