https://kotlinlang.org logo
#language-evolution
Title
# language-evolution
m

mbonnin

02/21/2023, 2:54 PM
Certainly a long shot but are there any discussions about introducing types that are completely erased (not just generics) in Kotlin? A bit like the typescript type system. At built time, all the type checking would happen. At run time the objects could be some
Map
-like type I guess and property accesses would be cast to the build-time type (and assert if wrong). Does that make any sense?
e

eygraber

02/21/2023, 3:02 PM
Out of curiosity, what would be the benefit of that?
m

mbonnin

02/21/2023, 3:06 PM
I'm generating models for GraphQL queries and it can become quite complex to the point that it generates a lot of code that takes lots of time to compile and load
And I don't really need runtime information because the objects are "verified" to be of the "expected" shape by the server (and it could also be validated client side if needed too)
Looks like the TS folks have it easier
e

eygraber

02/21/2023, 3:13 PM
generates a lot of code that takes lots of time to compile
Wouldn't a build time type checker have the same issue? Or does the type checking take a negligible amount of time?
m

mbonnin

02/21/2023, 3:14 PM
Yea I guess compile time would be in the same ballpark I guess. But not having to emit .class files and what not, I'm hoping it can be a bit faster
Currently an issue we have is that class names become so long that they don't fit on the 256 Mac-OS file name limit
Also this generated code goes through kapt and ksp and other things that have to process it. If we skip all of that, I'm hoping to save a bunch on compile time
And runtime is also a thing obviously
c

Casey Brooks

02/21/2023, 3:20 PM
Maybe generating value classes might help with the runtime issue? That would probably be a pretty big change to the library/code-gen, though. Alternatively, maybe you don’t need to do everything strictly through the GraphQL library? It’s kinda gross, but GraphQL is ultimately just a layer over REST, so you could just send a POST request with the GraphQL query in the body, and the result will just be normal JSON that could be deserialized to
JsonElement
with #serialization (or other similar types from other serialization libs)
m

mbonnin

02/21/2023, 3:21 PM
Maybe generating value classes might help with the runtime issue?
Maybe! Will check this!
send a POST request with the GraphQL query in the body, and the result will just be normal JSON that could be deserialized to
JsonElement
That works of course but the developer experience is nothing similar to having in-IDE autocomplete, inline documentation, deprecations, etc...
c

Casey Brooks

02/21/2023, 3:23 PM
Yeah, it’s just a fault with GraphQL in general. It’s supposed to be a language-neutral tool, but like most things web-related, really only works well with JS.
m

mbonnin

02/21/2023, 3:24 PM
You can feel it's designed for the web first but the Kotlin experience is really good too. The type system maps nicely and not having to write a serializer and having autocomplete + schema from your API right in your IDE is pretty great
It's only for the edge cases/huge schemas where you can feel the weight of the type system
e

ephemient

02/21/2023, 3:47 PM
Casey, is your suggestion something like
Copy code
value class Response(private val data: Map<String, Any>) {
    val foo: Foo
        get() = Foo(data["foo"] as Map<String, Any>)
    val optional: String?
        get() = data["optional"] as String?
}
etc.?
unfortunately I don't think it really saves on compile time, because Kotlin still generates boxed classes for every value class
c

Casey Brooks

02/21/2023, 3:49 PM
Yeah, that’s the basic idea that came to mind when Martin suggested having classes backed by a map-like object
e

ephemient

02/21/2023, 3:51 PM
Scala does have structural types (that aren't real classes), but the implementation is pretty hairy and I don't think it would fly in Kotlin
m

mbonnin

02/21/2023, 3:56 PM
Thanks for the pointer. 'structural types' sounds exactly like what I was looking for
Mmm without the reflection bits I guess...
e

ephemient

02/21/2023, 4:02 PM
well, it is better in Scala 3, it can be implemented without reflection https://docs.scala-lang.org/scala3/reference/changed-features/structural-types-spec.html
that would be a bit more likely for Kotlin, but require compiler support
y

Youssef Shoaib [MOD]

02/24/2023, 5:05 AM
You can even do
Copy code
object MapDelegate {
    operator fun <R> getValue(map: Map<String, Any>, prop: KProperty<*>): R = map[prop.name] as R
}
@JvmInline value class Response(private val data: Map<String, Any>): Map<String, Any> by data 

val Response.foo: Foo? by MapDelegate
where MapDelegate can be used as a delegate for any object that is a
Map<String, Any>
. Sadly value classes don't allow doing
by underlyingValue
for some reason, and so I had to define them as extension properties. Only issue is that sadly the name of the property is accessed through the
KProperty
object, which requires an object to exist per property.
e

elizarov

02/24/2023, 9:44 AM
We plan to do this with the further work on the contracts. The prototype we’ve developed allows declaring types like this:
Copy code
typealias PositiveInt = Int requires { it > 0 }
The additional requirement is completely erased at run-time but is checked at compile-time, so this code will not compile:
Copy code
val x: Int = getSomeInt()
val y: PositiveInt = x // cannot assign PositiveInt to Int
But this code will compile:
Copy code
val x: Int = getSomeInt()
require(x > 0)
val y: PositiveInt = x // OK
You can imagine using it with other types like Strings to represent domain-specific restricted string subsets, maps, etc.
K 1
m

mbonnin

02/24/2023, 9:46 AM
Oooohh interesting 👀 . Is there a KEEP/Youtrack were I can follow progress?
e

elizarov

02/24/2023, 10:30 AM
KT-51417 Restricted types
22 Views