I ran the following code in both kotlinc
and ki
(github)
data class Person(val name: String, val roles: List<String>)
val m = Person("bob", mutableListOf("developer"))
m.roles.addFirst("a")
In kotlinc
, I got an error message:
> kotlinc -script Immutable.kts
Immutable.kts:4:9: error: unresolved reference 'addFirst'.
m.roles.addFirst("a")
^
However, ki
allowed me to modify the mutable list roles
:
> ki
ki-shell 0.5.2/1.7.0
type :h for help
[0] data class Person(val name: String, val roles: List<String>)
[1] val m = Person("bob", mutableListOf("developer"))
[2] m.roles.addFirst("a")
[3] m.roles
res3: List<String> = [a, developer]
So, why the code returns two different outcomes depending on how it was executed?
I got confused by the use of listOf()
and mutableListOf()
. I understand that listOf()
creates an immutable list (addFirst()
is not available, so we cannot change the list), whereas mutableListOf()
returns a mutable list (addFirst()
is available, so we can change the list). However, that behavior does not apply when using data classes in kotlinc
, is that correct? Such a difference is expected when using ki
?
I am using these versions:
$ kotlinc -version
info: kotlinc-jvm 2.0.0 (JRE 22+36-2370)
$ javac -version
javac 22
$ ki --version
ki-shell 0.5.2/1.7.0
The compiler respects strictly the publicly declared types. The roles
attribute is of type List
, so not mutable. Therefore, you cannot add elements to it, because there is no guarantee that the underlying list instance is mutable.
I think Ki might work more as a debugger, and automatically check the runtime type to infer what are available methods.
To sum up: in term of Kotlin syntax, the compiler is strict and right, and Ki is more permissive because, as a debugger, it performs additional checks underneath to ease on the fly evaluations.