I love the conciseness that stems from Kotlin requ...
# language-proposals
i
I love the conciseness that stems from Kotlin requiring variables to be initialized when declared. I also enjoy the terseness of type inference. I think the combination could be improved if Kotlin added short and byte literals. I also think double literals would be more concise if 'd/D' was required. I imagine that ship has sailed, but it would be nice if it was at least supported. Then we could enforce its use by convention with linters. (To preempt any counter arguments of, "Why not
var i = 0i
for integers then?", I'll quote David Sedaris, and say that hopefully we can all, "...denounce the very idea as grotesque, and unrealistic." 😉)
Copy code
var bool = false // Boolean
var b = 0b // Byte. Does not compile. Has to be "= 0.toByte()", or "var b: Byte = 0".
var c = 'c' // Char
var s = 0s // Short.  As with Byte, does not compile.
var i = 0 // Int
var l = 0L // Long. Lowercase 'l' not supported.
var f = 0.0f // Float. 'F' also supported.
var d = 0.0d // Double. Does not compile, as 'd/D' not supported.
Updated proposal to account for hex literals for bytes and shorts (as with longs), and also to guess at what this might look like for the upcoming unsigned integral types (https://discuss.kotlinlang.org/t/when-does-bit-fiddling-come-to-kotlin/2249):
Copy code
var bool = false // Boolean
var b = 0y // Byte. Uppercase 'Y' also supported.
var hb = 0x0y // Byte (hex)
var ub = 0uy // UByte. Uppercase 'U' also supported.
var uhb = 0x0uy // UByte
var c = 'c' // Char
var s = 0s // Short. Uppercase 'S' also supported.
var hs = 0x0s // Short (hex)
var us = 0us // UShort
var uhs = 0x0us // UShort (hex)
var i = 0 // Int
var hi = 0x0 // Int (hex)
var ui = 0u // UInt
var uhi = 0x0u // UInt (hex)
var l = 0L // Long. Lowercase 'l' also supported.
var hl = 0x0L // Long (hex)
var ul = 0UL // ULong. Lowercase 'u' also supported.
var uhl = 0x0UL // ULong (hex)
var f = 0.0f // Float. Uppercase 'F' also supported.
var d = 0.0d // Double. Uppercase 'D' also supported.
So, the master list is: y/Y, uy/UY, s/S, us/US, u/U, l/L, ul/UL, f/F, d/D.
👍 1
😖 1
g
Just for information, there is also proposal about literals for BigDecimal/BigInteger https://github.com/Kotlin/KEEP/pull/24
👍 1
🙁 1
b
This is starting to look like C… I don’t like it
i
@benleggiero, What specifically don't you like about it? (Without details it's hard to move the conversation forward.)
b
Just the mass of different ways to type an integer without using a type name. I’m very much enjoying the plain-jane literals I use at work in Swift; the typing is always inferred from the context. Sometimes, yes, I have to do it explicitly, but that usually indicates that I’m shoving too much complex code into too small a space (poor maintainability), or I’m using an API wrong. I feel dizzy imagining looking at a sea of suffixed numbers in the future… why do all this stuff that’s been done since the 70s when other technologies have demonstrated that there are better ways that work well in the field? Why not infer that
val n: Double = 12
is
12.0
? Why is
val m = 6 as Byte
bad but
takeByte(6)
OK? There are better refinements to Kotlin’s number literal system than appending cryptic single-character typecodes. The following point has nothing to do with this proposal, but while I’m ranting about Kotlin types, why do we still call them
Byte
,
Short
,
Int
,
Long
,
Float
, and
Double
? How is that easier/more natural/better than
Int8
,
Int16
,
Int32
,
Int64
,
Float32
, and
Float64
? Then, we could let
Int
and
Float
be aliases for the numbers in the system’s native word size, which should make things better in general (fewer overflows, some operations faster, etc.)
g
It’s just naming, used by Java and some other languages, don’t see any reason to prefer some of them
Also in most cases you don’t need byte and short, just because it’s int in runtime
Not fixed size of int is actually really dangerous thing, your code became platform specific. Also this is useless on JVM and JS, Native has own types and type aliases for different word lenght
cryptic single-character typecodes
Type literals already here, we have
F
and
L
and we have exponential notation:
42e10
, and new type literals just addition to avoid long type declaration, especially with unsigned types
b
It’s just naming
Yeah, and I dislike it. Opinions 😛 I love that in Kotlin I can ignore them: https://github.com/BlueHuskyStudios/Blue-Base/blob/master/JVM/src/org/bh/tools/base/abstraction/Abstracted%20Number%20Types.kt
Don’t need byte and short
I agree! In my profession, I use Swift’s
Int
, and in my hobby I use my own
Integer
(a
typealias
in the above link).
Int
automagically matches the bitwidth of the target architecture, and I’d like to do that one day with my
Integer
.
Not fixed size is dangerous
I disagree. In fact, its safer in my experience. It means slightly better performance for free, longer arrays on wider architectures, and near-free adoption of new architectures. In my head, JVM and JS are ‘architectures’ just like x86 and ARM64. So, though the JVM’s native width is always 32, so is x86. In my #multiplatform project, I don’t need to worry about juggling things (theoretically, unfortunately, in Kotlin; practically, though, in Swift).
we have
F
and
L
and we have exponential notation:
42e10
I don’t like
F
and
L
and think they should go away, too. I enjoy exponentiation in a literal because it is very useful for writing functions that are heavy on the maths. I already don’t like seeing
10l
and having to pause to figure out if it’s
101
or
10L
. I don’t enjoy the idea of seeing
0b10l + 5BS - 0xADEU
and taking several seconds to figure out what’s really going on there
i
@benleggiero Thanks for all the details. Interesting points. Going the Swift route, and removing all type suffixes for literals, we're left with declaration site type inference only being available for Boolean, Char, Int, and Double:
Copy code
var bool = false // Boolean
var b: Byte = 0
var hb: Byte = 0x0
var ub: UByte = 0
var uhb: UByte = 0x0
var c = 'c' // Char
var s: Short = 0
var hs: Short = 0x0
var us: UShort = 0
var uhs: UShort = 0x0
var i = 0 // Int
var hi = 0x0 // Int
var ui: UInt = 0
var uhi: UInt = 0x0
var l: Long = 0
var hl: Long = 0x0
var ul: ULong = 0
var uhl: ULong = 0x0
var f: Float = 0.0
var d = 0.0 // Double
I think I'm partial to the suffixes, but not by much. I could get used to either. The problem with proposing to remove them is that it's a breaking syntax change. I imagine that would be a tough sell given the extent of this concern. If so, that leaves two options: propose nothing, which is a viable choice; or propose the added suffixes for at least byte and short (if not double as well, and presumably unsigned when that arrives). Thoughts? Alternatives?
b
Perhaps a non-breaking middle ground would be to allow existing suffixes, but not require them going forward. Also, explicit typing like you show wouldn’t always be required. For instance, the following is not allowed today, but in my opinion (Swift style) should be:
Copy code
fun parseHttpStatus(status: Short) {
    when (status) {
        200 -> println("All good") // Today, compiler error: "Incompatible types: Int and Short"
        else -> println("Error $status")
    }
}
This is confusing and inconsistent to me, because this is just fine today:
Copy code
fun makeShort(s: Short) = s

val x = makeShort(200)
So the compiler already does type inference of some integer literals, but not all, and it’s not customizable.