Possible in Kotlin to annotate a parameter as "a s...
# getting-started
r
Possible in Kotlin to annotate a parameter as "a set that has at least 1 element of type Foo (but may have extra non-Foo objects"? I can't just do
x: Set<Foo>
or that requires that all elements of the set be a
Foo
(ed
c
What is the type relationship between
Foo
and the other elements of the set?
r
a bit of effort to explain. it is for a game dev pattern. Just trust me that this is reasonable and thought through
i want a solution that does not require there to be any type relation between elements of the set
like, "this set has at least 1 number, and then any other type of element"
k
It sounds as if a
Pair<Foo, Set<Any>>
might be a better fit.
k
Even
Set<Foo>
is not saying “all elements are
Foo
and there is at least 1 element in there”. That’s just not what generics are for.
And even if you could, what would the compiler be able to do for iterating over set elements?
c
i want a solution that does not require there to be any type relation between elements of the set
That is, by definition,
Set<Any>
.
r
@Ray Rahke What game dev pattern? The only one that pops into mind that sort of fits this description is ECS. Whatever it is, I would recommend looking up libraries that implement this pattern and see what they do.
r
@Ruckus it is ECS.
Entity
has a
components
set
MutableSet<Component>
where
Compoenent
is an abstract base class. I have functions that receive
x: Entity
, but have no knowledge that this entity has a
Physics
component
I want a way to say
Copy code
fun fn(x: Entity<but who is guaranteed to have a Physics component in their .components set>) {
  // do things that work on the assumption that entities has a Physics component
}
No it is different. I am not saying "This set has anything, who knows what". I am saying "This set has at least 1 foo, guaranteed, but may have anything else in addition"
or in my case, "This Entity's
.components
is guaranteed to have a
Component
of subclass type
Physics
, but may have other
Component
objects too like
Sprite
and
Health"
I am wanting to avoid having to constantly do runtime if checks like
Copy code
fn SomethingRelatingToPhysics(entity: Entity) {
  if (entity.hasComponent<Physics>() == false) {
     throw error
  }
  physics.GetConfidently<Physics>()
}
k
This is just not supported
How do you see this code looking like if Kotlin generics supported such a case?
Even today, generic collection signatures say what that collection has when it’s not empty. There’s no annotation on a collection that says “I’m not empty”
r
@Kirill Grouchnikov
How do you see this code looking like if Kotlin generics supported such a case?
If You could annotate a Set<> has definitely having at least some Foo element, then it is trivial
I would write
Entity<Physics>
and then pass that argument down into the
val components:  MutableSet<At least one Physics>
s
Well, there are no magic annotations to indicate types of only some elements of collection in Kotlin. Even if there were, how would you expect them to work without runtime checks? Assuming you indicated method's parameter as
MutableSet<Any, but with at least one Physics>
, it pretty much wouldn't be possible for the compiler to handle such check by itself with built-in collection types.
MutableSet
is an interface, it has no constructor, there can by many implementations to it. Sets can be created empty, with single value and with multiple values. All mutations happen in runtime and can be result of conditions which are also evaluated in runtime, so it's pretty much not possible for the compiler to track collections states deterministically. It looks to me as your best bet is to either use
Pair<Physics, Set<Any>>
as previously suggested, or even better, create your own dedicated class that defines the shape of the contract you need and use it wherever appropriate.
t
You'll have to maintain this invariant yourself. Rather than a Set, make a class that contains a Set (or other members) and that ensure that it is always created with at least one Physics, can't have all of them removed, etc.
Can there be more than one Physics? If not, then you can maintain a dedicated slot for a Physics instance.