-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding meta queries to support combinations of queries as queries. #291
Conversation
I'm not entirely sure I'm convinced by the ergonomics of this or why this being raised as a PR without first raising an issue to discuss the feature request. |
I'm personally using these with an extension trait to make it more ergonomic. Apologies for not raising an issue first. I've raise #294 just now. |
It looks like the structs you are defining aren't being given a consistent set of derives? They should all really be deriving the same common set of Debug, Copy, Clone, PartialEq and Eq. The compiler issue you're showing here is down to the structs you've defined not having any trait bounds I suspect? Taking the #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct NotQuery<Q>(pub Q); Here /// A query to be run against client windows for identifying specific windows
/// or programs.
pub trait Query<X: XConn> {
/// Run this query for a given window ID.
fn run(&self, id: Xid, x: &X) -> Result<bool>;
/// The negation of this query
fn not(self) -> NotQuery<X, Self>
where
Self: Sized,
{
NotQuery {
inner: self,
_phantom: std::marker::PhantomData,
}
}
}
/// The logical negation of `Q`.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct NotQuery<X: XConn, Q: Query<X>> {
inner: Q,
_phantom: std::marker::PhantomData<X>,
}
impl<X, Q> Query<X> for NotQuery<X, Q>
where
X: XConn,
Q: Query<X>,
{
fn run(&self, id: Xid, x: &X) -> Result<bool> {
Ok(!self.inner.run(id, x)?)
}
} Exposing the inner All that said, I'm still not convinced that I fully see the utility of the |
Thanks for the pointers. Not sure why I'd not thought of This looks much simpler, and I like the concrete types. Though I was wondering if returning EDIT: In defense of my prior implementation, I'd added the methods to an extension trait because it didn't make sense to allow people to override them just by implementing |
Once thing I'm not sure about is whether using @favilo do you have any preference on that side of things? |
Hmm. The idea of just And that's a great point about not being able to construct the types outside of this crate. You've convinced me that we don't need an extension trait. I'll go ahead and make that change tomorrow morning. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to go after addressing the two comments! 🙂
The larger point to decide on is explicit generics vs trait objects for the wrapped queries. Happy to discuss here in the PR comments or if you'd prefer we can use the discord and then summarise what we decide here for future reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! Thank you for this @favilo 😄
- `AndQuery` - `OrQuery` - `NotQuery` - `AnyQuery` - `AllQuery`
This makes the public interface more simple. The `'static` bound is not terribly onerous, since we are not passing a reference to `self`, we are consuming self, and returning a new thing. Since owned objects are by definition `'static`, this shouldn't matter.
Adding structs:
AndQuery
OrQuery
NotQuery
And combinator methods in the
Query
trait in order to make these usable.