-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Add methods to return the inner value for direction types #12516
Conversation
Add `vec2` method for Dir2 Add `vec3` method for Dir3 Add `vec3a` method for Dir3A
Welcome, new contributor! Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨ |
I just realized that these methods is probably inaccessible unless specifying the type name because of the auto deref. |
I'm not sure this is the best approach. There is already Maybe the documentation can be improved to describe how to get the inner value? |
It does seem like Can you elaborate on your |
It's clear right away on how to access the
If we look it the other way around, implementing deref-polymorphism is not necessary but just to reduce boilerplate and so does
Basically, getters is just a lot more simpler that avoid issues. The code is easily parsed in mind when written, |
Absolutely! As it stands, deref polymorphism is useful, but as detailed in here, this is completely hidden from user. It should be clear for everyone that we're abusing deref to access the inner value. I'm not very familiar with Bevy. From my outside perspective, deref polymorphism is known as an anti-pattern and I wouldn't implement it in my library, but I'm not against it if it your decision that you guys have made. I just hope that when this is implemented, it will be documented. Also another example on when deref is less useful. |
There is no polymorphism here, it's a new-type pattern.
In our case, let d = Dir3::X;
let xz = d.xz(); // d acting like a `Vec3`
let vec3 = *d; // If a Vec3 is needed, just deref copy it I've opened a follow-up issue to add the missing |
It's a new-type pattern that implements deref polymorphism pattern via the
This is exactly deref polymorphism. Deref polymorphism description:
The only use for implementing Let's looks in the deref polymorphism example: use std::ops::Deref;
struct Foo {}
impl Foo {
fn m(&self) {
//..
}
}
struct Bar {
f: Foo,
}
impl Deref for Bar {
type Target = Foo;
fn deref(&self) -> &Foo {
&self.f
}
}
fn main() {
let b = Bar { f: Foo {} };
b.m();
} Here's the simplified implementation of Vec3 and Dir3: use std::ops::Deref;
struct Vec3 {
x: f32,
y: f32,
z: f32,
}
impl Vec3 {
fn xz(&self) {
}
}
struct Dir3(Vec3);
impl Deref for Dir3 {
type Target = Vec3;
fn deref(&self) -> &Self::Target {
&self.0
}
}
fn main() {
let d = Dir3(Vec3 { x: 1., y: 0., z: 0. });
let xz = d.xz();
} This is deref polymorphism according to the example. It's true that the official docs of Deref mention this kind of usage. But its usage outlined by the community is that it only should be implemented for types that "intuitively can be dereferenced" such as Intended uses from the unofficial docs:
If we described it like this, this might fits for the
These statements contradict themselves. Here below is the subtyping definition from a google search:
|
Interesting discussion here. Removing our use of Deref would be controversial, so let's call that out of scope for this PR. I have been swayed a bit, and would be interested in seeing follow up. This "anti-pattern" is certainly common, but that doesn't mean it's good use here. Regarding the proposed changes, I think discovery is worth some redundancy. I support having access methods in addition to Deref+From. Personally I would just call all of these into_vec. |
I'm lukewarm in favor of this if it's called |
I don't have strong opinions on the topic, but for some prior art: Nalgebra's Personally I consider our direction types to be Bevy's equivalents of Nalgebra's unit vectors and think of them primarily as vectors with extra restrictions. The direction types are newtypes of the vector types, and implementing For naming, Glam has methods like |
I like to follow the naming guidelines generally. I decided to use these names for the initial commit because:
I agree that using only I will make the method const. |
Whoops, I missed that this takes borrowed self and does an implicit copy. to_vec2/3/3a seems like the way to go then, considering it would be best to avoid ambiguity with Vec. Do I have that naming convention right? |
I guess ownership-wise
and Edit: The guidelines also don't have our "borrowed -> owned" case for a Copy type, so don't think that necessary applies for |
crates/bevy_math/src/direction.rs
Outdated
@@ -136,6 +136,11 @@ impl Dir2 { | |||
pub fn from_xy(x: f32, y: f32) -> Result<Self, InvalidDirectionError> { | |||
Self::new(Vec2::new(x, y)) | |||
} | |||
|
|||
/// Returning the inner [`Vec2`] |
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.
This comment format is quite strange. The verb should generally be in the present tense, not present continuous.
/// Returning the inner [`Vec2`] | |
/// Returns the inner [`Vec2`] |
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.
My bad. English is not my first language.
https://stackoverflow.com/a/73861738
I'd use |
Renamed `Dir2::vec2` to `Dir2::to_vec2` Renamed `Dir3::vec3` to `Dir2::to_vec3` Renamed `Dir3A::vec3a` to `Dir2::to_vec3a` Make `Dir2::to_vec2` const Make `Dir2::to_vec3` const Make `Dir2::to_vec3a` const
I'll suggest once more that if we want a |
Rename `Dir2::to_vec2` to `Dir2::as_vec2` Rename `Dir3::to_vec3` to `Dir3::as_vec3` Rename `Dir3A::to_vec3a` to `Dir3a::as_vec3a`
I can get onboard with as. The name standard is a little ambiguous between as and to here. |
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.
Sorry this ended up with so much bike shedding.
My bad if I may have been a bit unclear on the explanation of things. This is my first actual PR attempt after all 😃. Just finnally gets to contribute to something I like. The summary for adding getters is that it would've been more ergonomic long-term because of its simple usage. |
Objective
Currently in order to retrieve the inner values from direction types is that you need to use the
Deref
trait orFrom
/Into
.Deref
that is currently implemented is an anti-pattern that I believe should be less relied upon.This pull-request add getters for retrieving the inner values for direction types.
Advantages of getters:
From
/Into
will require fully qualified syntax from time to time.Disadvantages of getters:
Advantages of deref polymorphism:
Disadvantages of deref polymorphism:
More detail here.
Edit: Update information for From/Into trait.
Edit: Advantages and disadvantages.
Solution
Add
vec2
method for Dir2.Add
vec3
method for Dir3.Add
vec3a
method for Dir3A.