Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Adding to_degrees() and to_radians() methods to f32 and f64 seems a little out of place, considering f32 and f64 are numbers without units. Why not include to_celsius() and to_fahrenheit() then?


Technically radians and degrees are dimensionless since they're ratios.

More to the point, though, is 'sin' and 'cos' are also methods, so having 'to_degrees' as a method seems reasonable.


Also, methods can be called with a function-like syntax, if you prefer:

    let r = f32::to_radians(5.0);
    
    let x: f32 = 5.0;
    let r = x.to_radians();


Shouldn't to_degrees and to_radians be part of a trait that f32 and f64 (and potentially other types) both implement, rather than being independent methods directly on f32 and f64?


Over the course of Rust's history, we have tried a number of times to get a trait hierarchy for numerics working, and it's always had problems. It's still a general open question.


I'm not suggesting a trait hierarchy for numerics, or a numerical tower. I'm purely suggesting putting individual methods or families of related methods into independent traits that each numeric type can implement. For instance:

    trait AngleConversion {
        fn to_degrees(&self) -> Self;
        fn to_radians(&self) -> Self;
    }

    impl AngleConversion for f32 {
        ...
    }

    impl AngleConversion for f64 {
        ...
    }
Operators like + and / already live in traits; why not put methods like these into traits as well, so that users can implement them for their own types (variable-precision floats, decimal floating point, etc)?

(As a side note, can a trait accept an AsRef<Self> in place of &self or self, so that register-sized objects implementing Copy don't need to use &self?)


As always, it's a tradeoff. Doing something as a trait is hard for its own reasons, at least in a standard library. Should radians and degrees be two traits, or one? If we pick wrong, are we okay with having that be stable forever?

Plus, since you can define your own traits, if this is functionality you need, you can just do it, and delegate to the inherent implementation for those two types.


We really do need to spend time on the numerics APIs though... I would love to pour some time into it again... just figuring out how to fit it in with all the other stuff I'm doing :(

I agree with the caution though. This takes time to get right.


The advantage of the current approach is that you can just define the traits you need in your crate, and the standard library does not have to stabilize unrefined interfaces.


I'm kinda weirded out by non-idempotent `to_foo()` methods...


So you can write

  value.to_radians().to_radians()
then? Weird.


Why? It's like pressing some button on scientific calculator twice. It's just a function.


These are the sorts of things type systems try and help avoid. Having the same crappy behavior as an '80s scientific calculator isn't exactly something to strive for.

That said, this is probably such a simple use that it's not worth having Degree and Radian classes in core.


Not really. I'm for strong typing, but not all mathematical concepts need to be a separate type. Should we have separate type for 'ratio' or 'real' or 'natural'? A radian is still represented as a number -- specifically a float, generally. This is more like Rust building out a standard Math library, a la Node.js or C/C++. Since rust is aiming at being a C replacement, I can understand why they'd include this.


It's a number associated with a unit. Making it a distinct type, even when the underlying representation is a float, makes it harder to make mistakes by substituting or combining units inappropriately.

This sort of stuff works really well when the type system incorporates units of measure directly (usually as some kind of generic type parameter). F# is a good example.


This is similar to having 3D position and direction in different types (e.g. point and vector instead of a generic 4-component vector). It looks nice in theory, and it is 'type safe' (e.g. you can't add 2 points, only point+vector or vector+vector), but writing real-world code with this is awkward.


Some languages do include "natural" in their numeric tower.


Hm, I'm likely thinking about it wrong, but I don't see why you'd even necessarily want a type system to stop that... Is it not similar to running, which I expect to work?:

    var s1 = "blah"
    var s2 = s1 as string
    var s3 = s2 as string
edit: Nevermind, I guess you're wanting like types for units of measurement. Sounds interesting.


Most readers would expect the "as string" statement to be idempotent; to_radians() isn't, because it's actually implicitly degrees_to_radians(). If your type system isn't going to keep track of which quantities were already degrees, then your function names should be a little more explicit about the fact that value.to_radians().to_radians() is both converting and reinterpreting, twice.


I see, I had missed that detail. Thanks for the explaining it!

Is the best way to solve that problem by introducing "unit measurement" types that are more specific than general numerical types? Or is there another way? Or even a general concept I can go read about? Thanks in advance!


Last I checked, scientific calculators had degrees and radians as modes. This made pressing the button idempotent, an appropriate compromise given the lack of types.


Probably because those are normal mathematical operations to convert between different units of measurement for the same abstract thing in math.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: