Static arrays work as dynamic arrays

#1

Out of bounds is a great feature, and one of the important reasons for using a language like Kotlin instead of JavaScript.

Sometimes you want to define an array that is always of a the same size (hence static, but not immutable). This is interesting information for programmers and the compiler/interpreter.

In Kotlin Array(2){0}, IntArray(2), StringArray(2) and so on exists for this. - In Java you have Object[2], Int[2] and String[2].

Like with ArrayList I expect an IntArray to work the same in JVM and JS. That is not the case.

If I have an IntArray of size two and put something into index 42, it does so fine, and if I read from index 42, I just get a null.

If I have an Array of size two and put something into index 42, it does so fine, and if I read from index 42, I get the value.

All these operations should give “index out of bound” because it should be a static array of size 2.

val test_intArray = IntArray(2)
val test_Array = Array(2){0}
test_intArray[42] = 42
test_Array[42] = 42
println("IntArray index 42: " + test_intArray[42]) // Yields null.
println("Array index 42: " + test_Array[42]) // Yield 42.

2 Likes
#2

Ok. Look:

java.lang. ArrayIndexOutOfBoundsException: 42

From your example runned above jdk.

And:

var test_intArray = new Int32Array(2);
var test_array = Array_0(2);

Resulting code compiled from your example with kotlin2js.

Kotlin-stdlib-js is just wrapper around native (for tech stack) stdlib such as kotlin-stdlib-jdk and even kotlin-stdlib-native. In this way you got “sweet” syntax, familiar semantics and no compatibility issues for preferred framework. Unfortunately there is no nice solution for “strict” stdlib without compatibility cost. But you can define own structures like FixedArray which throws IndexOutOfBoundsException in own lib. In fact it will wrap js array, but why not.

#3

I still think this is an issue, especially when writing multiplatform code. Base types of the language should not behave differently on different platforms. Not sure what the right solution is though. I guess the generated js code could add bounds checks. Not sure what the performance impact of this is.

If this is an intended behavior it should at least be documented, which it is not (as far as I can tell).

#4

We have young developing language from professionals who think that js-codegen “compiler” intended behavior is intendend for all. Of course it should be documented, but now stdlib-js has empty *-javadoc.jar in maven-repo. On the other hand semantics should be hidden and kotlin Array documentation has no words about IndexOfBounds for any platform (if i got one in java - i got it from java platform, not from kotlin code). For multiplatform code kotlin has experimantal feature with specific building process.
Сomplexity and issues of platform-specific implementation are the cost of syntax sweetness and universality. Compact kotlin code is more complex than java, js or cpp. Just like you can write 42 in hex string as 0x2A and 42 in binary string as 101010 - you can write more complex code in kotlin with less instructions. That means this instructions is more complex itself. And it’s not good and not bad. You just should be prepared. If we throw out all kotlin marketing - you should be more skillful in kotlin and common things for writing really good kotlin code. Sometimes better use native platform language. I spent about a year with kotlin pet-projects in my team before we started to use it in product app. As for platform-specific features in multiplatform code - they are always complex by default.

#5

@alexey_e Yes, as I tried to explain, I’m aware that it works differently, and yes it is, obliviously, because it directly translates to arrays in javascript.

My point was that this is bad because it means that semantics are different depending on compilation target.
Furthermore ArrayList and others are implemented correctly (i.e. they work the same) no matter the target. This suggests Array should be no different, and also means that stdlib-js is not just a simple wrapper.

Index out of bounds is an important feature. There needs to be a static sized array with this feature (because sometimes you want to be explicit about this to programmers and the compiler).

Of course you could argue that there should be access to the native array. If so it should be a new type of NativeArray instead of re-purposing the meaning of Array. - This line of thinking might spawn a lot of native constructs though. Like if javascript had its own ArrayList that behaved a bit different. This makes it even more clear that Array should be no exception.

2 Likes
#6

I agree wholeheartedly. The semantics of Kotlin Types should be the same regardless of the platform. Isn’t this also the reason why Kotlin’s Long type is not mapped to the Javascript Number?

Having said this, it is of uttermost importance to being able to create pure JS Arrays. Otherwise interoperability with JS code will be complicated. This can be solved by introducing a JsArray type that is available on JS platform only.

1 Like
#7

I believe this way adds a lots of platform-specific structures and gives us non-predictable interop issues. Maybe i’m wrong. May be it just because of engineering time limits in JB. But it seems like transparent mapping to platform stdlib was the desired feature at the beginning. As for me it’s not the problem to implement strict structure for platform without it. Or we can check “indicies” any time our algorythm needs fixed dataset. Depends on target.