brood icon indicating copy to clipboard operation
brood copied to clipboard

Viewing one of two views with `Either`

Open Anders429 opened this issue 2 years ago • 1 comments

Just an idea I had this afternoon:

There may be times where we want to have a view on exactly one of two component types. For example, a system could want entities that contain either component A or component B, but not both, and obtain either a mutable reference to A or an immutable reference to B. We can do this now with a view like Views!(&mut A, &B) combined with a filter to express an XOR (not going to write it out because it will be long), but we still have to match on both views in the iteration, and have a weird case where the views seem like they can both be None or both be Some, but the filter has to expressly forbid it.

To make this easier, I think we should add new view type in Either<&mut A, &B> (or whatever other views we want to put in there). This will, naturally, imply the XOR filter, but will also represent the exclusive disjunction directly in the view. There is no question about whether neither or both components is valid, because those states are no longer valid at all.

As far as claims go, a view of this type will make claims on components viewed in both sides. This can also be used for EntryViews, but I'm not sure what this will mean for internal queries: will they be allowed to query both components A and B together? There may also be some problems with subviews.

For resource views, this doesn't really make much sense, since both resources will always exist if they are contained in the resource component list. Just as entity::Identifier does not view resources, I think it best to not view them with Either (or Option, really, but at least that makes sense in that it has ).

There may be some use in nesting these views. If there are three components that want to be viewed with exclusive disjunction, this could be expressed with a nested Either<&A, Either<&B, &C>>. With a view like this, we still have only one valid state, and the filter should naturally follow.

Anders429 avatar Apr 24 '23 20:04 Anders429

For reference, the XOR filter would look like this:

filter::And<filter::Or<filter::Has<A>, filter::Has<B>>, filter::Not<filter::And<filter::Has<A>, filter::Has<B>>>>

This is the equivalent of (has(A) || has(B)) && !(has(A) && has(B)). I'm not sure if there is any value in adding a dedicated filter::Xor type.

Anders429 avatar Apr 24 '23 23:04 Anders429