Pasha Tsier
02/18/2020, 6:43 AM@comptime
annotation, or even as a Comptime<A> trait. They would act as normal variables but would be evaluated at compile time instead of at runtime. This would allow for very powerful patterns - doing things like compile time bounds or units of measure checking. It could even allow us to make the nullibility checking and elvis operators part of the standard library written in Kotlin, instead of being part of the compiler itselfMatej Drobnič
02/18/2020, 7:42 AMconstexpr
proposal on the issue tracker https://youtrack.jetbrains.com/issue/KT-14652Matej Drobnič
02/18/2020, 7:44 AMThis is one of such features that require a few really strong use cases before we consider them. Feel free to list the use cases in the comments below
Pasha Tsier
02/18/2020, 8:57 AMinline class BoundedArray(val arr: Array<String>, comptime val length: Int) {
fun zip(other: BoundedArray): BoundedArray {
assert(length == other.length)
...
}
}
where the length parameter is only present at compile time , and it verifies that for all callers of zip the two arrays are of the same length.Matej Drobnič
02/18/2020, 10:19 AMMatej Drobnič
02/18/2020, 10:20 AMDominaezzz
02/18/2020, 10:20 AMPasha Tsier
02/18/2020, 7:06 PMenum Dimension { METER, SECOND, KG }
data class UOM(val dims: MutableMap<Dimension, Int>) {
operator fun times(other: UOM): UOM {
val newMap = HashMap<Dimension, Int>()
for (dim in dims.entries) {
val otherDim = other.dims.get(dim.key)
if (otherDim == null) newMap.put(dim.key, dim.value)
else newMap.put(dim.key, dim.value + otherDim)
}
for (dim in other.dims.entries) {
if (!other.dims.contains(dim.key)) {
newMap.put(dim.key, dim.value)
}
}
return UOM(newMap)
}
}
inline class Unit(val value: Double, comptime uom: UOM) {
operator fun plus(other: Unit): Unit {
assert(uom == other.uom)
return Unit(value + other.value, uom)
}
operator fun times(other: Unit): Unit {
return Unit(value * other.value, uom * other.uom)
}
}
notice that the Unit class is an inline class, so the comptime uom would only be present at compile time. And yes, that does mean that you actually have to know your units at compile time, but often that’s actually true.
It is SOMEWHAT similar to C++ templates, but i feel like trying to achieve this same thing with template expansion would be more difficult and unergonomicDico
02/19/2020, 12:29 AMPasha Tsier
02/19/2020, 12:40 AMPasha Tsier
02/19/2020, 12:43 AMDico
02/20/2020, 9:48 AMDico
02/20/2020, 9:49 AMDico
02/20/2020, 9:50 AMPasha Tsier
02/20/2020, 10:05 PMfun a(x: Int) = x + 3
@inline fun b(x: Int, @comptime y: Int) {
val c = a(y)
return if (c > 4) 1 else 0
}
then the function “a” actually runs as part of the compilation of “b” , so either we have to be able to compile “a” before “b” or to interpret it. If i were building a brand new language, I would make it explicitly staged - the compiler compiles a “type level program”, which when run generates the “value level program”, which then gets compiled to the final bytecode. so the compilation pipeline would look like
[Source Program] -- compile --> [CodeGenerator] --run--> [Generated Source] --compile--> ByteCode
I’m honestly not entirely sure how we would do this in the context of the existing compiler, but probably by having some restrictions on the code that can be marked as @comptime (only pure functions, only immutable data, no state) and then having an interpreter, but compiling would also work as long as we can actually run the output of our compilation.Dico
02/21/2020, 1:16 AM