Johan
11/13/2024, 8:47 AMenum class Result {
}
sealed interface Review
sealed interface LengthReview : Review {
val length: Result
}
sealed interface WidthReview : Review {
val width: Result
}
data class Foo(
override val length: Result,
override val width: Result,
) : LengthReview, WidthReview
fun Review.getAllValues(): List<Result> = buildList {
// Get all sealed subinterfaces of Review
val list = mutableListOf<Result>()
// get result from length and width
if(this is WidthReview) {
list.add(width)
}
if(this is LengthReview) {
list.add(length)
}
}
Without defining every sub-interface in an if(this is ..Review), when() would be nice, since it forces me to check every subinterface
when(this) {
is WidthReview
...
}
But when stops on match in kotlinJohan
11/13/2024, 8:54 AMval results = this::class.declaredMemberProperties.mapNotNull {
val value = it.getter.call(this)
if (value is Result) {
value
} else {
null
}
}
This works, but not really what I wantedDavid Kubecka
11/13/2024, 8:58 AMResult
property in which case it would be sensible to have val result: Result
already in Review
• Or not all your Review subinterfaces have the result in which case your current code seems perfectly appropriate.
Of course, you can try to use reflection but in my experience, it's generally not a good idea to use it in these specific cases (in contrast to generic libraries like JSON handling).David Kubecka
11/13/2024, 8:59 AMResult
you might consider creating another common/base interface for them.Johan
11/13/2024, 9:02 AMdata class Foo(
override val length: Result,
override val width: Result,
) : LengthReview, WidthReview
And in some way get all "reviews"David Kubecka
11/13/2024, 9:11 AMJohan
11/13/2024, 9:32 AMDavid Kubecka
11/13/2024, 9:37 AMJohan
11/13/2024, 9:43 AMloke
11/14/2024, 8:26 AMAPLFunction
that describes a specific instantiation of a function (a call to a function at a specific line of code) in my programming language. Some functions can contain references to one or more other function instantiations (for example, when doing function composition), but most functions do not.
The compiler needed to find all functions that are referenced by a function in order to compute closures correctly. If I was pure JVM I could have used reflection to find and references like val ref: APLFunction
in the class. This was of course not an alternative, so instead I did this (simplified):
abstract class APLFunction(val fns: List<APLFunction> = emptyList()) {
...
}
An APLFunction
subclass that does embed other function calls, would then do this:
class SomeFunction(pos: FunctionInstantiation, fn0: APLFunction, fn1: APLFunction) : APLFunction(listOf(fn0, fn1)) {
...
}
In my application I have hundreds of these, so I needed a concise way to do it, and lots of if-statements wasn't something I wanted to use.David Kubecka
11/14/2024, 8:55 AMloke
11/14/2024, 9:05 AMval foo get() = fns[0]
and then explusively use foo
to refer to it. In principle, I could add a test case that checks all subclasses of APLFunction
to ensure they don't have any fields that store values of type APLFunction
.Johan
11/14/2024, 9:41 AMDavid Kubecka
11/14/2024, 10:06 AMabstract class ResultsHolder(val results: List<Result>)
data class Foo(
override val length: Result,
override val width: Result,
) : LengthReview, WidthReview, ResultsHolder(listOf(length, width))
fun ResultsHolder.getAllValues() = results // you probably don't even need this
But as I said this comes at a price of the tight coupling.