Are arrays like @Nullable, or primatives?
I like the example with @Nullable
. I think Kotlin did sacrifice when they chose nullable types instead of full union types (which I think was a nice pragmatic choice). I don’t think it’s analogous to Arrays though but I can see where you’re coming from.
Here’s an analogy that might help explain where I see it differently: Instead of comparing looking at @Nullable
, look at how Kotlin handles primitives–they don’t exist in Kotlin. Kotlin (and other pure OOP languages before it) takes something that a beginner Java coder considers absolutely necessary and throws it out the window for something to create a more sound conceptual model.
Other solutions that need to be considered?
I’m not against improving array usage, I just don’t want to rush into it.
Side note about array literals
Most people I’ve talked to that want literal arrays with a very specific solution and haven’t considered the larger possibilities. Sometimes they haven’t even considered the options for general collection literals (set, map, or arbitrary types).
I like that your OP details the issue because creating multiple dimension collections is the problem. If the issue is instantiating collections, we should solve that use case instead of trying to force-fit the Java syntax. It may be the best option but we should arrive there ourselves.
You can!
fun main() {
val array2d = array2d<Int>(3, 3) { 0 }
println(array2d.map { it.toList() }.joinToString("\n"))
}
inline fun <reified T> array2d(n: Int, m: Int, intitializer: () -> T) = Array<Array<T>>(n) {
Array<T>(m) { intitializer() }
}
Let’s consider a few possibilities for initializing an array (these are just function signature ideas. I didn’t implement all of them):
val myArray = Array<Int>(n, m) {0} // Would require 'namespace' or Companion extension on Array*
val myArray = array<Int>(3,3,3) // 3x3x3 array. Any dimension using vararg but losing safety.
// Or maybe:
val myArray = array3d<Int>[3][3][3] // Odd but possible.
// Or something like this:
val myArray: Array3d<Int> = array(3, 3, 3) // Same as first but keeping type safety.
// Of course we can always typealias for long generic class declarations.
typealias Array3d<T> = Array<Array<Array<T>>>
There’s many options other than pushing through the old system of raw array literals (Java’s array literals) that could help us deal with arrays. Just look at KMath.
Another element that should be part of the discussion is immutable collections. IMO they are often the first thing left out of a request for array literals and are important to consider how changes would enable/limit the options for immutable collections.
How often are array issues a problem?
I agree that for math, graphs, and many more cases, arrays are useful. And under the hood, arrays are essential.
My holdback here is not that it would be nice to create multi-dimension arrays with brackets, but that we also should consider other collections than an array. For example, creating multi-dimension lists I suspect is far more common.
Any syntax we consider would lock us out of other uses as well. One of the popular multi-receiver syntax ideas used brackets, for example.
Of course the minus 100 point rule still applies.
Are arrays commonly the best option for X?
I think it’s worth narrowing the concept of arrays to say that, at a high level for almost all uses, “array” is used to mean “fixed-size list” (even to the point that I would earmark an API using an array as a potential code smell in case they could be changed to a List).
I really like how Kotlin has removed a lot of the magic behind Arrays and made them feel more like a normal object.
What about in the future?
Personally, I do think Kotlin will add collection literals at some point down the line. I see this going three ways:
- Array literals and declaration syntax (Java style) - This is the weakest option IMO–it’s also the most requested option that I’ve seen. It makes a rarely used collection special while passing up on better opportunities.
- A few collection literal types (Groovy / Python style) - This option is allowing syntax for a few different types of collection literals and/or type declarations.
- General collection syntax or something else - There’s plenty of other ideas to explore. One is allowing users to support literal collection syntax for their own class. I don’t have much to say about this. I’ll leave that to more creative with language design.