Open umut-sahin opened 2 months ago
I wonder if such a feature can be added "just like that". For some "synonyms" maths can work differently, e.g. if you do
#[derive(Synonym)]
pub struct Seconds(f64);
then you should be able to multiply seconds by a number and expect the result to be seconds and rather avoid multiplying seconds by seconds.
OTOH this crate is not designed to create a unit of measurement. I will think about it.
I don't think the scope of the crate needs to be expanded to that. Already there are:
To me this crate is just creating new types to be used in signatures to avoid bugs (or in my case, to use it for my Bevy components) and this feature request is to make that easier to work with.
#[derive(Synonym)]
pub struct Speed(pub f64);
pub fn double_player_speed(player_query: Query<&mut Speed, With<Player>>) {
let mut player_speed = player_query.single_mut();
player_speed *= 2.00;
// is better then
// player_speed *= Speed(2.00);
// or
// player_speed.0 *= 2.00;
}
or
#[derive(Synonym)]
pub struct Health(pub f64);
pub fn increment_player_health(player_query: Query<&mut Health, With<Player>>) {
let mut player_health = player_query.single_mut();
player_health += 1.00;
// is better then
// player_health += Health(1.00);
// or
// player_health.0 += 1.00;
}
or
#[derive(Synonym)]
pub struct Health(pub f64);
pub fn player_death(player_query: Query<&Health, With<Player>>) {
let player_health = player_query.single();
if player_health <= 0.00 { ... }
// is better then
// if player_health <= Health(0.00) { ... }
// or
// if player_health.0 <= 0.00 { ... }
}
(this one might require an explicit deref with * but you get the idea)
But this is just a minor inconvenience, not a blocker, so it's all good either way.
If you prefer to go with units, maybe you can:
Units wouldn't get mixed and most of the functionality would be retained (except for multiplying or dividing two Speeds
for example).
Wait, actually you can support division as well, it might result in the underlying type:
let x = Speed(3.00);
let y = Speed(6.00);
assert_eq!(x / y, 0.50); // x / y is an actual f64
It can be useful for calculating proportions.
So yeah it looks pretty good with just disabling multiplication between new types and changing the result of division :stuck_out_tongue:
Yes, I'm not aiming for a units lib. You got the point of the lib very well with
To me this crate is just creating new types to be used in signatures to avoid bugs (or in my case, to use it for my Bevy components)
However, I guess you already see my point that it makes more sense to multiply the speed by a float and not by another speed. Perhaps supporting addition and subtraction is very straightforward. RE multiplication/division - since the crate version is still at 0.x, I could perhaps experiment with implementing newtype
[*/] underlying type
resulting in a newtype
and give configuration to change the behaviour.
By intuition, this is the most common case.
To me, the best approach is this: | Operation | With New Type | With Underlying Type |
---|---|---|---|
Add/Sub | ✓ -> New Type | ✓ -> New Type | |
Eq/PartialEq/Ord/PartialOrd | ✓ -> bool | ✓ -> bool | |
Mul | x (as it would change the unit) | ✓ -> New Type | |
Div | ✓-> Underlying Type (to calculate proportion) | ✓-> New Type | |
AddAssign/SubAssign | ✓ | ✓ | |
MulAssign/DivAssign | x (as it would change the unit) | ✓ |
It doesn't mess with the unit and provide as much functionality as possible!
Btw, I'd love to help with some of the issues I've created if you're interested. I think this is a really cool library and it'd massively improve some of the headaches of working with the new type paradigm.
Would be cool to be able to do: