-
Notifications
You must be signed in to change notification settings - Fork 25
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
Get rid of the lifetime parameters on Triple, Graph and Dataset #24
Comments
Removing lifetimes on Tripe and Quad is easy. I have a local branch that I'll push soon, where this is done. For Graph and Dataset, this is more tricky. The problem comes from the fact that Graph::Triple, which is the type returned by the iterating methods (triples, triples_with_s, etc.) sometimes needs a lifetime, especially when one wants the iterator to return references to internal triples owned by the graph. This is something that I would like to keep. As mentioned elsewhere, the cleanest solution would be generic associated types (GAT), but those are not expected to be stabilized before long... I have experimented with another approach, which tries to emulate somehow GAT, by using pointers under the hood, hence eschewing lifetime parameters, and wrapping them in a safe abstraction. I tried my best to make this approach easy enough for implementors of the Graph trait (although the documentations is still rough at the edges). https://gist.github.com/pchampin/7fbf3262ab22b6a0f6a6eae8a6aa938c @Tpt @MattesWhite anyonelse... your feedback would be much appreciated |
Your solution seems suitable.
|
I like @MattesWhite solution. A maybe dumb comment: are the NotNull pointers actually required in your solution? I believe you could do it with just references (but maybe I'm wrong). |
Well, this is not a dumb question 😁 . Indeed, they are not needed. I updated to a version with zero unsafe code. BTW with the removal of everything unsafe the name |
This type looks a lot like |
Cool :)
My solution has zero overhead in memory (PhantomData is 0-sized) and in runtime (provided the appropriate
Absolutely. I wouldn't hold my breath, though... GATs have been mentioned for a while now.
Very good point. The current approach (with method) evolved organically from previous attempts, but the constructor approach is much cleaner.
Actually, the raw pointers are hidden inside the GuardedTriple; neither implementors nor users will actually handle the pointers directly. Only a very daring implementor may have to write Now, regarding your variant: by using enums, you are introducing memory overhead (the enum takes as much space as the biggest variant), and runtime overhead (each call to triple methods will go through the If we were to accept a small overhead, there would be no need for this complex approach. We could simply go for dynamic dispatching with trait objects: trait Graph {
// note that the associated type Triple has vanished
fn triple<'s>(&'s self) -> Box<dyn Iterator<Item=Box<dyn Triple + 's>> + 's>
// ^^^^^^^^^^^^^^^^^^^^
// this is the big change
} I have considered this option. But, as I expressed before, I find it sad to renounce zero-cost abstract so close to the goal. And the proposed approach will allow for a smooth transition when GAT finally land (basically replace the associated type (sorry for the long answer) |
Of course but the types-signatures include raw pointers. Maybe it is already enough to hide them behind a typedef, e.g.
If I think further this might be a nice expressive way. Change the associated type of
Don't know if this realy works because I'm on mobile but I wanted to wright this thought down. |
Now I had some time to test out my proposal. Here are the results: https://gist.github.com/MattesWhite/f5daf2d38d36c4e325e00cbb41ec59e8#file-sophia_experiment_zero-rs The most notable difference is that I use new-types instead of typedefs to declare the |
That's roughly what I'm planning to do. I'm not decided on the terminology, though. I want to make easy to understand by implementors of the |
They are causing much complexity, especially the requirement for using higher-ranked type bound in some situations.
It might be better to give up some genericity in order to make the API easier to use.
The text was updated successfully, but these errors were encountered: