possible to make this destructuring syntax a reali...
# getting-started
r
possible to make this destructuring syntax a reality?
Copy code
val (foo, bar, qux) = Context.getInstances(Foo::class, Bar::class, Qux::class)
j
Yes, if you make
getInstances()
return a list, or anything that has
componentN()
functions
g
Or if you overload
componentN
manually for the result of
getInstance
function. If it is even possible.
e
you need to create separate container types for different sizes if you want it to be type-safe but it's perfectly doable
Copy code
data class ThreeInstances<One, Two, Three>(val one: One, val two: Two, val three: Three)

object Context {
    fun getInstances<One : Any, Two : Any, Three : Any>(one: KClass<One>, two: KClass<Two>, three: KClass<Three>): ThreeInstances<One, Two, Three>
}
that said, unless there is actually a benefit to doing those in a single call, you could just make a property delegate and get a nice syntax
Copy code
inline fun <reified T : Any> Context.getValue(thisRef: Any?, property: KProperty<T>): T

val foo: Foo by Context
val bar: Bar by Context
val qux: Qux by Context
3
K 2
r
@ephemient I want the function to have varargs so I can query for an arbitrary number of componets at once
the benefit to doing it in a single call is readability
@Joffrey it would return a list, but i am not sure how it would have type information to correspond to each destructured value
j
Ah right, I missed that part. It wouldn't. It would basically be
Any
for everything, so yeah it doesn't solve your problem.
But I personally vastly prefer ephemient's approach with delegates for readability. Having one line doesn't mean more readable in general, and here is a typical case where mapping types to variables visually is harder on one line
r
in the case of an ECS in game engine
Copy code
val (physics, graphics, health) = entity.getComponents(Physics::class, Graphics::class, Health::class)
this is not hard to visually map types and has better readability then manually doing 3
val
assignments (in terms of speed, important metric in readability)
after 10 minutes working in this codebase you learn the whole
val x = getComponents(X::class)
pattern, so you learn to ignore the right hand side of the equation etc.
it is just visual noise
i suppose that is the reasoning behind destructuring as a syntax to begin with
once you get the pattern of the right hand side you can just ignore it with one single brevity line of code assigning all the lefthands in one go
if you introspect about your inner psych while reading the two versions I think it is like 1: "Ok we have an
x
val, by getting component
X
. next we have a
y
val, by getting component
Y
then a
z
component, by getting component
Z
" that is a lot of distinct steps your brain has to parse. versus 2: "Okay we will have components
x,y,z
by getting components
X
,
Y
,
Z
that 2nd sort of expression is easier on the brain
j
I don't think that's quite correct. AFAIK, research shows our brain can process a certain number of elements (about 6-7) at once. If you drop a bunch of matches on the ground, you'll be able to know there are 5 of them without counting them sequentially, it just appears to you instantly. Same goes here. Whether you see a pattern:
Copy code
a - b - c = A - B - C
Or
Copy code
a - A
b - B
c - C
You'll process all elements immediately anyway. That said, the first option is more cluttered with extra syntax (e.g.
::class
), and more interlaced, so I would still argue it's slower to parse visually